Compare commits
14 Commits
d03e5ee5d9
...
v1.5.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4bbb8b0b38 | ||
|
|
1657e89ddb | ||
|
|
afa6d4c4de | ||
|
|
31a086e165 | ||
|
|
01cc243bcf | ||
|
|
25f5e28e56 | ||
|
|
e6588d3960 | ||
|
|
8f706b9fe7 | ||
|
|
f9c07a0346 | ||
|
|
a22957baa1 | ||
|
|
d7f3c64f63 | ||
|
|
29eea131b9 | ||
|
|
2dcef0936e | ||
|
|
20dd2a6d28 |
16
.github/workflows/build.yml
vendored
@@ -13,9 +13,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout PDFio sources
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
uses: actions/checkout@v4
|
||||
- name: Update Build Environment
|
||||
run: sudo apt-get update --fix-missing -y
|
||||
- name: Install Prerequisites
|
||||
@@ -23,7 +21,7 @@ jobs:
|
||||
- name: Configure PDFio
|
||||
run: ./configure --enable-debug --enable-sanitizer --enable-maintainer
|
||||
- name: Build PDFio
|
||||
run: make
|
||||
run: make "COMMONFLAGS=-g -fsanitize=address"
|
||||
- name: Test PDFio
|
||||
env:
|
||||
ASAN_OPTIONS: leak_check_at_exit=false
|
||||
@@ -39,9 +37,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout PDFio sources
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
uses: actions/checkout@v4
|
||||
- name: Configure PDFio
|
||||
run: ./configure --enable-debug --enable-sanitizer --enable-maintainer
|
||||
- name: Build PDFio
|
||||
@@ -57,11 +53,9 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout PDFio sources
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup MSBuild
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
- name: Nuget Restore
|
||||
run: nuget restore pdfio.sln
|
||||
- name: Build PDFio
|
||||
|
||||
2
.github/workflows/codeql.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout PDFio sources
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
||||
4
.github/workflows/coverity.yml
vendored
@@ -8,9 +8,7 @@ jobs:
|
||||
environment: Coverity
|
||||
steps:
|
||||
- name: Checkout PDFio sources
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
uses: actions/checkout@v4
|
||||
- name: Update Build Environment
|
||||
run: sudo apt-get update --fix-missing -y
|
||||
- name: Install Prerequisites
|
||||
|
||||
2
.gitignore
vendored
@@ -25,5 +25,5 @@
|
||||
/pdfio-*.zip*
|
||||
/testpdfio
|
||||
/testpdfio-*.pdf
|
||||
/testfiles/testpdfio-*.pdf
|
||||
/testttf
|
||||
/x64
|
||||
|
||||
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
||||
[submodule "ttf"]
|
||||
path = ttf
|
||||
url = https://github.com/michaelrsweet/ttf.git
|
||||
78
CHANGES.md
@@ -2,84 +2,6 @@ Changes in PDFio
|
||||
================
|
||||
|
||||
|
||||
v1.7.0 - YYYY-MM-DD
|
||||
-------------------
|
||||
|
||||
- Now use TTF 1.1 or later for font support.
|
||||
- Added support for basic compound stream filters for ASCII85Decode support
|
||||
(Issue #11)
|
||||
- Added support for LZWDecode filters (Issue #11)
|
||||
- Added support for writing object streams (Issue #101)
|
||||
- Added support for GIF files (Issue #145)
|
||||
- Added support for WebP files (Issue #144)
|
||||
- Added `pdfioPageGetXxx` functions to get values from the page dictionaries
|
||||
(Issue #150)
|
||||
- Fixed a buffer overflow in the (still not enabled) AES-256 code.
|
||||
|
||||
|
||||
v1.6.2 - YYYY-MM-DD
|
||||
-------------------
|
||||
|
||||
- Increased the maximum length of a single string to 128k (Issue #146)
|
||||
- Added missing range checks to `pdfioArrayCopy` and `pdfioDictCopy`.
|
||||
- Refactored PDF encryption code to fix unlocking with certain files.
|
||||
- Improved xref table loop detection (Issue #148)
|
||||
- Changed how duplicate objects are handled in PDF files (Issue #155)
|
||||
- Fixed xref reconstruction for objects lacking a `Type` value.
|
||||
- Fixed `pdfioPageOpenStream` for indirect `Contents` arrays.
|
||||
- Fixed an error propagation bug when reading too-long values (Issue #146)
|
||||
- Fixed a Clang warning.
|
||||
|
||||
|
||||
v1.6.1 - 2025-12-26
|
||||
-------------------
|
||||
|
||||
- Added missing input checking to `pdfioFileCreateFontObjFromBase` function.
|
||||
- Updated support for UTF-16 strings (Issue #141)
|
||||
- Updated Xcode project to use installed PNG library.
|
||||
- Fixed decryption of PDF files using an Encrypt dictionary instead of an
|
||||
indirect reference (Issue #139)
|
||||
- Fixed character range checking in a TTF support function.
|
||||
- Fixed some clang warnings.
|
||||
- Fixed the generated pkg-config file.
|
||||
|
||||
|
||||
|
||||
v1.6.0 - 2025-10-06
|
||||
-------------------
|
||||
|
||||
- Added generation of XMP metadata when writing PDFs (Issue #103)
|
||||
- Added "standard" `PDFIO_CS_CGATS001` color space for non-device CMYK
|
||||
(Issue #104)
|
||||
- Added CMYK JPEG support with embedded ICC profiles or using the CGATS001
|
||||
profile (Issue #104)
|
||||
- Added `pdfioFileAddOutputIntent` function to adding output intent information
|
||||
to a PDF file (Issue #104)
|
||||
- Added explicit support for warning messages (Issue #118)
|
||||
- Added `pdfioFileCreateFontObjFromData` function for embedding fonts in
|
||||
memory (Issue #120)
|
||||
- Added support for specifying PDF/A versions for created PDF files (Issue #122)
|
||||
- Added `pdfioContentBeginMarked` and `pdfioContentEndMarked` functions for
|
||||
creating tagged PDF content (Issue #123)
|
||||
- Added `pdfioFileGetLanguage` and `pdfioFileSetLanguage` functions for getting
|
||||
and setting the default/primary language of a PDF file (Issue #124)
|
||||
- Now add default grayscale, RGB, and CMYK profile resources to pages as needed
|
||||
(Issue #104)
|
||||
- Fixed unsupported filter error (Issue #130)
|
||||
- Fixed EOF comment written to the PDF (Issue #136)
|
||||
- Fixed TTF cmap underflow error.
|
||||
- Fixed some Clang warnings.
|
||||
|
||||
|
||||
v1.5.4 - 2025-08-26
|
||||
-------------------
|
||||
|
||||
- Updated indirect reference reading code to limit the range of generation
|
||||
numbers.
|
||||
- Updated error messages for too large tokens (Issue #131)
|
||||
- Fixed a JPEG copy bug (Issue #132)
|
||||
|
||||
|
||||
v1.5.3 - 2025-05-03
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -110,11 +110,10 @@ same guidelines as allowed by the language.
|
||||
|
||||
### Source Files
|
||||
|
||||
All source files names must be lowercase and should be 16 characters or less in
|
||||
length to ensure compatibility with older UNIX filesystems. Source files
|
||||
containing functions have an extension of ".c" for C source files. All
|
||||
"include" files have an extension of ".h". Tabs are set every 8 characters,
|
||||
columns, or spaces, with an indentation of 2 spaces in code.
|
||||
All source files names must be 16 characters or less in length to ensure
|
||||
compatibility with older UNIX filesystems. Source files containing functions
|
||||
have an extension of ".c" for C source files. All "include" files have an
|
||||
extension of ".h". Tabs are set to 8 characters or columns.
|
||||
|
||||
The top of each source file contains a header giving the purpose or nature of
|
||||
the source file and the copyright and licensing notice:
|
||||
@@ -142,8 +141,8 @@ private API header file will include the corresponding public API header file.
|
||||
All source code utilizes block comments within functions to describe the
|
||||
operations being performed by a group of statements; avoid putting a comment
|
||||
per line unless absolutely necessary, and then consider refactoring the code
|
||||
so that it is not necessary. C source files typically use the C99 comment
|
||||
format ("// comment"):
|
||||
so that it is not necessary. C source files use the C99 comment format
|
||||
("// comment"):
|
||||
|
||||
// Clear the state array before we begin...
|
||||
for (i = 0; i < (sizeof(array) / sizeof(sizeof(array[0])); i ++)
|
||||
@@ -160,17 +159,6 @@ format ("// comment"):
|
||||
sleep(1);
|
||||
} while (i == (sizeof(array) / sizeof(array[0])));
|
||||
|
||||
When passing literal argument values to functions, the argument name should be
|
||||
supplied as an inline comment:
|
||||
|
||||
// This function call lacks any inline comments so it is hard to
|
||||
// know what the numbers mean!
|
||||
do_something(filename, 1, 42);
|
||||
|
||||
// This uses inline comments to specify what the numbers mean and
|
||||
// makes the code easier to read and maintain:
|
||||
do_something(filename, /*initial_value*/1, /*count*/42);
|
||||
|
||||
|
||||
### Indentation
|
||||
|
||||
@@ -268,16 +256,16 @@ Return/output values are indicated using an "O" prefix, input values are
|
||||
indicated using the "I" prefix, and values that are both input and output use
|
||||
the "IO" prefix for the corresponding in-line comment.
|
||||
|
||||
The [`codedoc` documentation generator][CODEDOC] also understands the following
|
||||
The [`codedoc` documentation generator][1] also understands the following
|
||||
special text in the function description comment:
|
||||
|
||||
@deprecated@ - Marks the function as deprecated (not recommended
|
||||
for new development and scheduled for removal)
|
||||
@since VERSION@ - Marks the function as new in the specified version.
|
||||
@since version@ - Marks the function as new in the specified version.
|
||||
@private@ - Marks the function as private (same as starting the
|
||||
function name with an underscore)
|
||||
|
||||
[CODEDOC]: https://www.msweet.org/codedoc
|
||||
[1]: https://www.msweet.org/codedoc
|
||||
|
||||
|
||||
### Variables
|
||||
@@ -385,13 +373,11 @@ The following variables are defined in the makefile:
|
||||
|
||||
- `AR`; the static library archiver command,
|
||||
- `ARFLAGS`; options for the static library archiver,
|
||||
- `BUILDROOT`: the destination root directory when installing - also picks up
|
||||
the value of the `DESTDIR`, `DSTROOT`, and/or `RPM_BUILD_ROOT` environment
|
||||
variables,
|
||||
- `CC`; the C compiler command,
|
||||
- `CFLAGS`; options for the C compiler,
|
||||
- `CODESIGN_IDENTITY`: the code signing identity,
|
||||
- `CPPFLAGS`; options for the C preprocessor,
|
||||
- `DESTDIR`/`DSTROOT`: the destination root directory when installing.
|
||||
- `DSO`; the shared library building command,
|
||||
- `DSOFLAGS`; options for the shared library building command,
|
||||
- `LDFLAGS`; options for the linker,
|
||||
@@ -409,6 +395,5 @@ The following standard targets are defined in the makefile:
|
||||
- `all`; creates the static library and unit test program.
|
||||
- `clean`; removes all target programs libraries, documentation files, and
|
||||
object files,
|
||||
- `doc`; creates the library documentation files using [`codedoc`][CODEDOC],
|
||||
- `install`; installs all distribution files in their corresponding locations.
|
||||
- `test`; runs the unit test program, building it as needed.
|
||||
|
||||
21
EXAMPLES.md
@@ -2,12 +2,17 @@ PDFio Examples
|
||||
==============
|
||||
|
||||
The "examples" subdirectory contains example code showing how to do different
|
||||
things with PDFio:
|
||||
things with PDFio.
|
||||
|
||||
- `code128.c`: Shows how to embed and use a barcode font.
|
||||
- `image2pdf.c`: Shows how to embed and use an image file.
|
||||
- `md2pdf.c`: Shows how to generate pages with multiple fonts, embedded images,
|
||||
and headers and footers.
|
||||
- `pdf2text.c`: Shows how to extract plain text from a PDF.
|
||||
- `pdfioinfo.c`: Shows how to extract metadata from a PDF.
|
||||
- `pdfiomerge.c`: Shows how to merge two or more PDFs.
|
||||
|
||||
code128.c
|
||||
---------
|
||||
|
||||
This example shows how to embed and use a barcode font.
|
||||
|
||||
|
||||
md2pdf.c
|
||||
--------
|
||||
|
||||
This example shows how to generate pages with multiple fonts, embedded images,
|
||||
and headers and footers.
|
||||
|
||||
135
INSTALL.md
@@ -1,135 +0,0 @@
|
||||
Building, Testing, and Installing PDFio
|
||||
=======================================
|
||||
|
||||
This file describes how to compile, test, and install the PDFio library from
|
||||
source code. For more information on PDFio see the file called `README.md`.
|
||||
|
||||
|
||||
Getting the Code
|
||||
----------------
|
||||
|
||||
> Note: Do not use the ZIP file available via the Github "Code" button on the
|
||||
> main project page, as that archive is missing the TTF submodule and will not
|
||||
> compile.
|
||||
|
||||
The source code is available in release tarballs or via the Github repository.
|
||||
For a release tarball, run the following commands:
|
||||
|
||||
tar xvzf pdfio-VERSION.tar.gz
|
||||
cd pdfio-VERSION
|
||||
|
||||
Similarly, the release ZIP file can be extracted with the following commands:
|
||||
|
||||
unzip pdfio-VERSION.zip
|
||||
cd pdfio-VERSION
|
||||
|
||||
From the Github sources, clone the repository with the `--recurse-submodules`
|
||||
option *or* use the `git submodule` command:
|
||||
|
||||
git clone --recurse-submodules git@github.com:michaelrsweet/pdfio.git
|
||||
cd pdfio
|
||||
|
||||
git clone git@github.com:michaelrsweet/pdfio.git
|
||||
cd pdfio
|
||||
git submodule update --init --recursive
|
||||
|
||||
To update an already-cloned repository:
|
||||
|
||||
git pull
|
||||
git submodule update --init --recursive
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
PDFio requires the following to build the software:
|
||||
|
||||
- A C99 compiler such as Clang, GCC, or MS Visual C
|
||||
- A POSIX-compliant `make` program
|
||||
- A POSIX-compliant `sh` program
|
||||
- libpng (<https://www.libpng.org/>) 1.6 or later for full PNG image support
|
||||
(optional)
|
||||
- libwebp (<https://developers.google.com/speed/webp>) 1.0 or later for WebP
|
||||
image support (optional)
|
||||
- ZLIB (<https://www.zlib.net/>) 1.1 or later for compression support
|
||||
|
||||
IDE files for Xcode (macOS/iOS) and Visual Studio (Windows) are also provided.
|
||||
|
||||
On a stock Ubuntu install, the following command will install the various
|
||||
prerequisites:
|
||||
|
||||
sudo apt-get install build-essential libpng-dev libwebp-dev zlib1g-dev
|
||||
|
||||
|
||||
Building and Installing on Linux/Unix
|
||||
-------------------------------------
|
||||
|
||||
PDFio uses a configure script on Unix systems to generate a makefile:
|
||||
|
||||
./configure
|
||||
|
||||
If you want a shared library, run:
|
||||
|
||||
./configure --enable-shared
|
||||
|
||||
The default installation location is "/usr/local". Pass the `--prefix` option
|
||||
to make to install it to another location:
|
||||
|
||||
./configure --prefix=/some/other/directory
|
||||
|
||||
Other configure options can be discovered by using the `--help` option:
|
||||
|
||||
./configure --help
|
||||
|
||||
Once configured, run the following command to build the library:
|
||||
|
||||
make all
|
||||
|
||||
Finally, run the following command to install the library, documentation, and
|
||||
examples on the local system:
|
||||
|
||||
sudo make install
|
||||
|
||||
Use the `BUILDROOT` variable to install to an alternate root directory:
|
||||
|
||||
sudo make BUILDROOT=/some/other/root/directory install
|
||||
|
||||
> Note: PDFio also supports the GNU `DSTROOT`, Apple/Darwin `DESTDIR`, and
|
||||
> Red Hat `RPM_BUILD_ROOT` variables to specify an alternate root directory.
|
||||
|
||||
|
||||
### Running the Unit Tests
|
||||
|
||||
PDFio includes a unit test program that thoroughly tests the library. Type the
|
||||
following to run the unit tests:
|
||||
|
||||
make test
|
||||
|
||||
Detailed test results are saved to the "test.log" file.
|
||||
|
||||
|
||||
Building on Windows with Visual Studio
|
||||
--------------------------------------
|
||||
|
||||
The Visual Studio solution (`pdfio.sln`) is provided for Windows developers and
|
||||
generates the PDFIO1 DLL. You can also use NuGet to install the `pdfio_native`
|
||||
package.
|
||||
|
||||
You can build and run the `testpdfio` unit tests target from within Visual
|
||||
Studio to verify the functioning of the library.
|
||||
|
||||
|
||||
Building on macOS with Xcode
|
||||
----------------------------
|
||||
|
||||
The Xcode project (`pdfio.xcodeproj`) is provided for macOS developer which
|
||||
generates a static library that will be installed under "/usr/local". Run the
|
||||
following command to build and install PDFio on macOS:
|
||||
|
||||
sudo xcodebuild install
|
||||
|
||||
Alternately you can add the Xcode project to a workspace and reference the PDFio
|
||||
library target as a dependency in your own project.
|
||||
|
||||
You can build and run the `testpdfio` unit tests target from within Xcode to
|
||||
verify the functioning of the library.
|
||||
48
Makefile.in
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Makefile for PDFio.
|
||||
#
|
||||
# Copyright © 2021-2026 by Michael R Sweet.
|
||||
# Copyright © 2021-2025 by Michael R Sweet.
|
||||
#
|
||||
# Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
# information.
|
||||
@@ -69,8 +69,6 @@ top_srcdir = @top_srcdir@
|
||||
|
||||
BUILDROOT = $(DSTROOT)$(RPM_BUILD_ROOT)$(DESTDIR)
|
||||
|
||||
TTFDIR = @TTFDIR@
|
||||
|
||||
|
||||
# Build commands...
|
||||
.SUFFIXES: .c .h .o
|
||||
@@ -91,7 +89,6 @@ PUBOBJS = \
|
||||
pdfio-crypto.o \
|
||||
pdfio-dict.o \
|
||||
pdfio-file.o \
|
||||
pdfio-lzw.o \
|
||||
pdfio-md5.o \
|
||||
pdfio-object.o \
|
||||
pdfio-page.o \
|
||||
@@ -102,14 +99,17 @@ PUBOBJS = \
|
||||
pdfio-token.o \
|
||||
pdfio-value.o
|
||||
LIBOBJS = \
|
||||
$(PUBOBJS)
|
||||
$(PUBOBJS) \
|
||||
ttf.o
|
||||
OBJS = \
|
||||
$(LIBOBJS) \
|
||||
testpdfio.o
|
||||
testpdfio.o \
|
||||
testttf.o
|
||||
TARGETS = \
|
||||
$(LIBPDFIO) \
|
||||
$(LIBPDFIO_STATIC) \
|
||||
testpdfio
|
||||
testpdfio \
|
||||
testttf
|
||||
DOCFILES = \
|
||||
doc/pdfio.html \
|
||||
doc/pdfio-512.png \
|
||||
@@ -135,30 +135,16 @@ EXAMPLES = \
|
||||
|
||||
|
||||
# Make everything
|
||||
all:
|
||||
if test "x$(TTFDIR)" != x; then \
|
||||
echo Making all in $(TTFDIR)...; \
|
||||
(cd $(TTFDIR); $(MAKE) $(MFLAGS) all) || exit 1; \
|
||||
fi
|
||||
$(MAKE) $(MFLAGS) $(TARGETS)
|
||||
all: $(TARGETS)
|
||||
|
||||
|
||||
# Clean everything
|
||||
clean:
|
||||
if test "x$(TTFDIR)" != x; then \
|
||||
echo Cleaning in $(TTFDIR)...; \
|
||||
(cd $(TTFDIR); $(MAKE) $(MFLAGS) clean) || exit 1; \
|
||||
fi
|
||||
echo Cleaning build files...
|
||||
rm -f $(TARGETS) $(OBJS)
|
||||
|
||||
|
||||
# Install everything
|
||||
install: $(TARGETS)
|
||||
if test "x$(TTFDIR)" != x; then \
|
||||
echo Installing in $(TTFDIR)...; \
|
||||
(cd $(TTFDIR); $(MAKE) $(MFLAGS) install) || exit 1; \
|
||||
fi
|
||||
echo Installing header files to $(BUILDROOT)$(includedir)...
|
||||
$(INSTALL) -d -m 755 $(BUILDROOT)$(includedir)
|
||||
for file in $(PUBHEADERS); do \
|
||||
@@ -200,8 +186,9 @@ install: $(TARGETS)
|
||||
|
||||
|
||||
# Test everything
|
||||
test: testpdfio
|
||||
./testpdfio 2>test.log
|
||||
test: testpdfio testttf
|
||||
./testttf 2>test.log
|
||||
./testpdfio 2>>test.log
|
||||
LANG=fr_FR.UTF-8 ./testpdfio 2>>test.log
|
||||
|
||||
|
||||
@@ -245,16 +232,23 @@ testpdfio: testpdfio.o libpdfio.a
|
||||
$(CC) $(LDFLAGS) -o $@ testpdfio.o libpdfio.a $(LIBS)
|
||||
|
||||
|
||||
# TTF test program
|
||||
testttf: ttf.o testttf.o
|
||||
echo Linking $@...
|
||||
$(CC) $(LDFLAGS) -o testttf ttf.o testttf.o $(LIBS)
|
||||
|
||||
|
||||
# Dependencies
|
||||
$(OBJS): pdfio.h pdfio-private.h Makefile
|
||||
pdfio-content.o: pdfio-content.h
|
||||
testpdfio.o: test-internal.h
|
||||
pdfio-content.o: pdfio-content.h ttf.h
|
||||
testttf.o: ttf.h
|
||||
ttf.o: ttf.h
|
||||
|
||||
|
||||
# Make documentation using Codedoc <https://www.msweet.org/codedoc>
|
||||
DOCFLAGS = \
|
||||
--author "Michael R Sweet" \
|
||||
--copyright "Copyright (c) 2021-2026 by Michael R Sweet" \
|
||||
--copyright "Copyright (c) 2021-2025 by Michael R Sweet" \
|
||||
--docversion $(PDFIO_VERSION)
|
||||
|
||||
.PHONY: doc
|
||||
|
||||
2
NOTICE
@@ -1,6 +1,6 @@
|
||||
PDFio - PDF Read/Write Library
|
||||
|
||||
Copyright © 2021-2026 by Michael R Sweet.
|
||||
Copyright © 2021-2025 by Michael R Sweet.
|
||||
|
||||
(Optional) Exceptions to the Apache 2.0 License:
|
||||
================================================
|
||||
|
||||
92
README.md
@@ -1,10 +1,10 @@
|
||||
PDFio - PDF Read/Write Library
|
||||
pdfio - PDF Read/Write Library
|
||||
==============================
|
||||
|
||||

|
||||

|
||||
[](https://github.com/michaelrsweet/pdfio/actions/workflows/build.yml)
|
||||
[](https://scan.coverity.com/projects/michaelrsweet-pdfio)
|
||||
[](https://github.com/michaelrsweet/pdfio/actions/workflows/build.yml)
|
||||
[](https://scan.coverity.com/projects/michaelrsweet-pdfio)
|
||||
|
||||
PDFio is a simple C library for reading and writing PDF files. The primary
|
||||
goals of PDFio are:
|
||||
@@ -20,29 +20,77 @@ goals of PDFio are:
|
||||
PDFio is *not* concerned with rendering or viewing a PDF file, although a PDF
|
||||
RIP or viewer could be written using it.
|
||||
|
||||
Copyright © 2021-2026 by Michael R Sweet. PDFio is licensed under the Apache
|
||||
License Version 2.0 with an (optional) exception to allow linking against GNU
|
||||
GPL2-only software. See the files `LICENSE` and `NOTICE` for more information.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
PDFio requires the following to build the software:
|
||||
|
||||
- A C99 compiler such as Clang, GCC, or MS Visual C
|
||||
- A POSIX-compliant `make` program
|
||||
- ZLIB (<https://www.zlib.net>) 1.1 or higher
|
||||
|
||||
IDE files for Xcode (macOS/iOS) and Visual Studio (Windows) are also provided.
|
||||
|
||||
|
||||
Reading the Documentation
|
||||
-------------------------
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
Initial documentation to get you started is provided in the root directory of
|
||||
the PDFio sources:
|
||||
See the man page (`pdfio.3`) and full HTML documentation (`pdfio.html`) for
|
||||
information on using PDFio.
|
||||
|
||||
- `CHANGES.md`: A list of changes for each release of PDFio.
|
||||
- `CODE_OF_CONDUCT.md`: Code of conduct for the project.
|
||||
- `CONTRIBUTING.md`: Guidelines for contributing to the project.
|
||||
- `INSTALL.md`: Instructions for building, testing, and installing PDFio.
|
||||
- `LICENSE`: The PDFio license agreement (Apache 2.0).
|
||||
- `NOTICE`: Copyright notices and exceptions to the PDFio license agreement.
|
||||
- `README.md`: This file.
|
||||
- `SECURITY.md`: How (and when) to report security issues.
|
||||
|
||||
You will find the PDFio documentation in HTML, EPUB, and man formats in the
|
||||
`doc` directory.
|
||||
Installing PDFio
|
||||
----------------
|
||||
|
||||
Examples can be found in the `examples` directory.
|
||||
PDFio uses a configure script on Unix systems to generate a makefile:
|
||||
|
||||
*Please read the documentation before asking questions.*
|
||||
./configure
|
||||
|
||||
If you want a shared library, run:
|
||||
|
||||
./configure --enable-shared
|
||||
|
||||
The default installation location is "/usr/local". Pass the `--prefix` option
|
||||
to make to install it to another location:
|
||||
|
||||
./configure --prefix=/some/other/directory
|
||||
|
||||
Once configured, run the following to make the library:
|
||||
|
||||
make all
|
||||
|
||||
To test it, run:
|
||||
|
||||
make test
|
||||
|
||||
To install it, run:
|
||||
|
||||
sudo make install
|
||||
|
||||
|
||||
Visual Studio Project
|
||||
---------------------
|
||||
|
||||
The Visual Studio solution ("pdfio.sln") is provided for Windows developers and
|
||||
generates the PDFIO1 DLL. You can also use NuGet to install the `pdfio_native`
|
||||
package.
|
||||
|
||||
|
||||
Xcode Project
|
||||
-------------
|
||||
|
||||
There is also an Xcode project ("pdfio.xcodeproj") you can use on macOS which
|
||||
generates a static library that will be installed under "/usr/local" with:
|
||||
|
||||
sudo xcodebuild install
|
||||
|
||||
|
||||
Legal Stuff
|
||||
-----------
|
||||
|
||||
PDFio is Copyright © 2021-2025 by Michael R Sweet.
|
||||
|
||||
This software is licensed under the Apache License Version 2.0 with an
|
||||
(optional) exception to allow linking against GPL2/LGPL2 software. See the
|
||||
files "LICENSE" and "NOTICE" for more information.
|
||||
|
||||
38
SECURITY.md
@@ -5,40 +5,12 @@ This file describes how security issues are reported and handled, and what the
|
||||
expectations are for security issues reported to this project.
|
||||
|
||||
|
||||
What is a Security Bug?
|
||||
-----------------------
|
||||
|
||||
Not every bug is a security bug.
|
||||
|
||||
Certain bugs that might be considered security bugs in a program, such as bugs
|
||||
that lead to a Denial of Service, are *not* considered security bugs simply
|
||||
because this project *does not provide a service*. Some might argue that, "my
|
||||
server uses this library and the bug in this library causes a denial of service
|
||||
for my server", however it is the responsibility of the *server* to protect
|
||||
against DoS attacks, not a subordinate library, because only the server knows
|
||||
what is an appropriate use of memory, CPU, time, and other resources.
|
||||
|
||||
Similarly, bugs caused by incorrect API usage such as passing `NULL` pointers
|
||||
where such pointers are not allowed, passing the wrong kinds of pointers or
|
||||
objects to an API, or using a private API are not security bugs because they
|
||||
are not caused by an attacker but by the developer.
|
||||
|
||||
Finally, bugs that only exist in unreleased (non-production) or inactive code
|
||||
are not security bugs because they do not affect ordinary users. See the
|
||||
[Supported Versions](#supported-versions) section below for more information
|
||||
about what versions of the project are covered by this security policy.
|
||||
|
||||
If the bug you've found falls into one of these three categories, please report
|
||||
the bug as an the ordinary project issue at
|
||||
<https://github.com/michaelrsweet/pdfio/issues>.
|
||||
|
||||
|
||||
Reporting a Security Bug
|
||||
------------------------
|
||||
|
||||
For the purposes of this project, a security bug is a software defect that
|
||||
allows a *local or remote user* to gain unauthorized access or privileges on the
|
||||
host computer or to causes the software to crash. Such defects should be
|
||||
host computer or to cause the software to crash. Such defects should be
|
||||
reported to the project security advisory page at
|
||||
<https://github.com/michaelrsweet/pdfio/security/advisories>.
|
||||
|
||||
@@ -46,6 +18,11 @@ Alternately, security bugs can be reported to "security AT msweet.org" using the
|
||||
PGP public key below. Expect a response within 5 business days. Any proposed
|
||||
embargo date should be at least 30 days and no more than 90 days in the future.
|
||||
|
||||
> *Note:* If you've found a software defect that allows a *program* to gain
|
||||
> unauthorized access or privileges on the host computer or causes the program
|
||||
> to crash, that defect should be reported as an ordinary project issue at
|
||||
> <https://github.com/michaelrsweet/pdfio/issues>.
|
||||
|
||||
|
||||
Responsible Disclosure
|
||||
----------------------
|
||||
@@ -91,9 +68,6 @@ example:
|
||||
1.0b2
|
||||
1.0rc1
|
||||
|
||||
Pre-release code in a Git branch ("master", "v1.6.x", etc.) is similarly *not*
|
||||
production release code.
|
||||
|
||||
|
||||
PGP Public Key
|
||||
--------------
|
||||
|
||||
78
config.guess
vendored
@@ -1,10 +1,10 @@
|
||||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright 1992-2025 Free Software Foundation, Inc.
|
||||
# Copyright 1992-2022 Free Software Foundation, Inc.
|
||||
|
||||
# shellcheck disable=SC2006,SC2268 # see below for rationale
|
||||
|
||||
timestamp='2025-07-10'
|
||||
timestamp='2022-09-17'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@@ -47,7 +47,7 @@ me=`echo "$0" | sed -e 's,.*/,,'`
|
||||
usage="\
|
||||
Usage: $0 [OPTION]
|
||||
|
||||
Output the configuration name of the system '$me' is run on.
|
||||
Output the configuration name of the system \`$me' is run on.
|
||||
|
||||
Options:
|
||||
-h, --help print this help, then exit
|
||||
@@ -60,13 +60,13 @@ version="\
|
||||
GNU config.guess ($timestamp)
|
||||
|
||||
Originally written by Per Bothner.
|
||||
Copyright 1992-2025 Free Software Foundation, Inc.
|
||||
Copyright 1992-2022 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
|
||||
help="
|
||||
Try '$me --help' for more information."
|
||||
Try \`$me --help' for more information."
|
||||
|
||||
# Parse command line
|
||||
while test $# -gt 0 ; do
|
||||
@@ -102,8 +102,8 @@ GUESS=
|
||||
# temporary files to be created and, as you can see below, it is a
|
||||
# headache to deal with in a portable fashion.
|
||||
|
||||
# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still
|
||||
# use 'HOST_CC' if defined, but it is deprecated.
|
||||
# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
|
||||
# use `HOST_CC' if defined, but it is deprecated.
|
||||
|
||||
# Portable tmp directory creation inspired by the Autoconf team.
|
||||
|
||||
@@ -123,7 +123,7 @@ set_cc_for_build() {
|
||||
dummy=$tmp/dummy
|
||||
case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
|
||||
,,) echo "int x;" > "$dummy.c"
|
||||
for driver in cc gcc c17 c99 c89 ; do
|
||||
for driver in cc gcc c89 c99 ; do
|
||||
if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
|
||||
CC_FOR_BUILD=$driver
|
||||
break
|
||||
@@ -155,9 +155,6 @@ Linux|GNU|GNU/*)
|
||||
|
||||
set_cc_for_build
|
||||
cat <<-EOF > "$dummy.c"
|
||||
#if defined(__ANDROID__)
|
||||
LIBC=android
|
||||
#else
|
||||
#include <features.h>
|
||||
#if defined(__UCLIBC__)
|
||||
LIBC=uclibc
|
||||
@@ -165,8 +162,6 @@ Linux|GNU|GNU/*)
|
||||
LIBC=dietlibc
|
||||
#elif defined(__GLIBC__)
|
||||
LIBC=gnu
|
||||
#elif defined(__LLVM_LIBC__)
|
||||
LIBC=llvm
|
||||
#else
|
||||
#include <stdarg.h>
|
||||
/* First heuristic to detect musl libc. */
|
||||
@@ -174,7 +169,6 @@ Linux|GNU|GNU/*)
|
||||
LIBC=musl
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
EOF
|
||||
cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
|
||||
eval "$cc_set_libc"
|
||||
@@ -465,7 +459,7 @@ case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
|
||||
UNAME_RELEASE=`uname -v`
|
||||
;;
|
||||
esac
|
||||
# Japanese Language versions have a version number like '4.1.3-JL'.
|
||||
# Japanese Language versions have a version number like `4.1.3-JL'.
|
||||
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
|
||||
GUESS=sparc-sun-sunos$SUN_REL
|
||||
;;
|
||||
@@ -634,8 +628,7 @@ EOF
|
||||
sed 's/^ //' << EOF > "$dummy.c"
|
||||
#include <sys/systemcfg.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
main()
|
||||
{
|
||||
if (!__power_pc())
|
||||
exit(1);
|
||||
@@ -719,8 +712,7 @@ EOF
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
int main ()
|
||||
{
|
||||
#if defined(_SC_KERNEL_BITS)
|
||||
long bits = sysconf(_SC_KERNEL_BITS);
|
||||
@@ -912,7 +904,7 @@ EOF
|
||||
fi
|
||||
;;
|
||||
*:FreeBSD:*:*)
|
||||
UNAME_PROCESSOR=`uname -p`
|
||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
||||
case $UNAME_PROCESSOR in
|
||||
amd64)
|
||||
UNAME_PROCESSOR=x86_64 ;;
|
||||
@@ -984,27 +976,7 @@ EOF
|
||||
GUESS=$UNAME_MACHINE-unknown-minix
|
||||
;;
|
||||
aarch64:Linux:*:*)
|
||||
set_cc_for_build
|
||||
CPU=$UNAME_MACHINE
|
||||
LIBCABI=$LIBC
|
||||
if test "$CC_FOR_BUILD" != no_compiler_found; then
|
||||
ABI=64
|
||||
sed 's/^ //' << EOF > "$dummy.c"
|
||||
#ifdef __ARM_EABI__
|
||||
#ifdef __ARM_PCS_VFP
|
||||
ABI=eabihf
|
||||
#else
|
||||
ABI=eabi
|
||||
#endif
|
||||
#endif
|
||||
EOF
|
||||
cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
|
||||
eval "$cc_set_abi"
|
||||
case $ABI in
|
||||
eabi | eabihf) CPU=armv8l; LIBCABI=$LIBC$ABI ;;
|
||||
esac
|
||||
fi
|
||||
GUESS=$CPU-unknown-linux-$LIBCABI
|
||||
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
|
||||
;;
|
||||
aarch64_be:Linux:*:*)
|
||||
UNAME_MACHINE=aarch64_be
|
||||
@@ -1070,15 +1042,6 @@ EOF
|
||||
k1om:Linux:*:*)
|
||||
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
|
||||
;;
|
||||
kvx:Linux:*:*)
|
||||
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
|
||||
;;
|
||||
kvx:cos:*:*)
|
||||
GUESS=$UNAME_MACHINE-unknown-cos
|
||||
;;
|
||||
kvx:mbr:*:*)
|
||||
GUESS=$UNAME_MACHINE-unknown-mbr
|
||||
;;
|
||||
loongarch32:Linux:*:* | loongarch64:Linux:*:*)
|
||||
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
|
||||
;;
|
||||
@@ -1234,7 +1197,7 @@ EOF
|
||||
GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
|
||||
;;
|
||||
i*86:OS/2:*:*)
|
||||
# If we were able to find 'uname', then EMX Unix compatibility
|
||||
# If we were able to find `uname', then EMX Unix compatibility
|
||||
# is probably installed.
|
||||
GUESS=$UNAME_MACHINE-pc-os2-emx
|
||||
;;
|
||||
@@ -1375,7 +1338,7 @@ EOF
|
||||
GUESS=ns32k-sni-sysv
|
||||
fi
|
||||
;;
|
||||
PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort
|
||||
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
|
||||
# says <Richard.M.Bartel@ccMail.Census.GOV>
|
||||
GUESS=i586-unisys-sysv4
|
||||
;;
|
||||
@@ -1597,12 +1560,6 @@ EOF
|
||||
*:Unleashed:*:*)
|
||||
GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
|
||||
;;
|
||||
x86_64:[Ii]ronclad:*:*|i?86:[Ii]ronclad:*:*)
|
||||
GUESS=$UNAME_MACHINE-pc-ironclad-mlibc
|
||||
;;
|
||||
*:[Ii]ronclad:*:*)
|
||||
GUESS=$UNAME_MACHINE-unknown-ironclad-mlibc
|
||||
;;
|
||||
esac
|
||||
|
||||
# Do we have a guess based on uname results?
|
||||
@@ -1626,7 +1583,6 @@ cat > "$dummy.c" <<EOF
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
int
|
||||
main ()
|
||||
{
|
||||
#if defined (sony)
|
||||
@@ -1811,8 +1767,8 @@ fi
|
||||
exit 1
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp nil t)
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "timestamp='"
|
||||
# time-stamp-format: "%Y-%02m-%02d"
|
||||
# time-stamp-format: "%:y-%02m-%02d"
|
||||
# time-stamp-end: "'"
|
||||
# End:
|
||||
|
||||
955
config.sub
vendored
399
configure
vendored
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.71 for pdfio 1.7.0.
|
||||
# Generated by GNU Autoconf 2.71 for pdfio 1.5.3.
|
||||
#
|
||||
# Report bugs to <https://github.com/michaelrsweet/pdfio/issues>.
|
||||
#
|
||||
@@ -610,8 +610,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='pdfio'
|
||||
PACKAGE_TARNAME='pdfio'
|
||||
PACKAGE_VERSION='1.7.0'
|
||||
PACKAGE_STRING='pdfio 1.7.0'
|
||||
PACKAGE_VERSION='1.5.3'
|
||||
PACKAGE_STRING='pdfio 1.5.3'
|
||||
PACKAGE_BUGREPORT='https://github.com/michaelrsweet/pdfio/issues'
|
||||
PACKAGE_URL='https://www.msweet.org/pdfio'
|
||||
|
||||
@@ -647,16 +647,13 @@ ac_includes_default="\
|
||||
#endif"
|
||||
|
||||
ac_header_c_list=
|
||||
enable_option_checking=no
|
||||
ac_subst_vars='LTLIBOBJS
|
||||
LIBOBJS
|
||||
WARNINGS
|
||||
CSFLAGS
|
||||
LIBPDFIO_STATIC
|
||||
LIBPDFIO
|
||||
TTFDIR
|
||||
subdirs
|
||||
PKGCONFIG_REQUIRES_PRIVATE
|
||||
PKGCONFIG_LIBPNG
|
||||
PKGCONFIG_REQUIRES
|
||||
PKGCONFIG_LIBS_PRIVATE
|
||||
PKGCONFIG_LIBS
|
||||
@@ -734,7 +731,6 @@ ac_subst_files=''
|
||||
ac_user_opts='
|
||||
enable_option_checking
|
||||
enable_libpng
|
||||
enable_libwebp
|
||||
enable_static
|
||||
enable_shared
|
||||
enable_debug
|
||||
@@ -751,7 +747,7 @@ CFLAGS
|
||||
LDFLAGS
|
||||
LIBS
|
||||
CPPFLAGS'
|
||||
ac_subdirs_all='ttf'
|
||||
|
||||
|
||||
# Initialize some variables set by options.
|
||||
ac_init_help=
|
||||
@@ -1299,7 +1295,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures pdfio 1.7.0 to adapt to many kinds of systems.
|
||||
\`configure' configures pdfio 1.5.3 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1365,7 +1361,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of pdfio 1.7.0:";;
|
||||
short | recursive ) echo "Configuration of pdfio 1.5.3:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1373,9 +1369,7 @@ Optional Features:
|
||||
--disable-option-checking ignore unrecognized --enable/--with options
|
||||
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
|
||||
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
|
||||
--disable-libpng use libpng for pdfioFileCreateImageObjFromFile,
|
||||
default=auto
|
||||
--disable-libwebp use libwebp for pdfioFileCreateImageObjFromFile,
|
||||
--enable-libpng use libpng for pdfioFileCreateImageObjFromFile,
|
||||
default=auto
|
||||
--disable-static do not install static library
|
||||
--enable-shared install shared library
|
||||
@@ -1466,7 +1460,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
pdfio configure 1.7.0
|
||||
pdfio configure 1.5.3
|
||||
generated by GNU Autoconf 2.71
|
||||
|
||||
Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
@@ -1519,39 +1513,6 @@ fi
|
||||
|
||||
} # ac_fn_c_try_compile
|
||||
|
||||
# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
|
||||
# -------------------------------------------------------
|
||||
# Tests whether HEADER exists and can be compiled using the include files in
|
||||
# INCLUDES, setting the cache variable VAR accordingly.
|
||||
ac_fn_c_check_header_compile ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
|
||||
printf %s "checking for $2... " >&6; }
|
||||
if eval test \${$3+y}
|
||||
then :
|
||||
printf %s "(cached) " >&6
|
||||
else $as_nop
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$4
|
||||
#include <$2>
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"
|
||||
then :
|
||||
eval "$3=yes"
|
||||
else $as_nop
|
||||
eval "$3=no"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||
fi
|
||||
eval ac_res=\$$3
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
printf "%s\n" "$ac_res" >&6; }
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
|
||||
} # ac_fn_c_check_header_compile
|
||||
|
||||
# ac_fn_c_try_link LINENO
|
||||
# -----------------------
|
||||
# Try to link conftest.$ac_ext, and return whether this succeeded.
|
||||
@@ -1660,6 +1621,39 @@ printf "%s\n" "$ac_res" >&6; }
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
|
||||
} # ac_fn_c_check_func
|
||||
|
||||
# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
|
||||
# -------------------------------------------------------
|
||||
# Tests whether HEADER exists and can be compiled using the include files in
|
||||
# INCLUDES, setting the cache variable VAR accordingly.
|
||||
ac_fn_c_check_header_compile ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
|
||||
printf %s "checking for $2... " >&6; }
|
||||
if eval test \${$3+y}
|
||||
then :
|
||||
printf %s "(cached) " >&6
|
||||
else $as_nop
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$4
|
||||
#include <$2>
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"
|
||||
then :
|
||||
eval "$3=yes"
|
||||
else $as_nop
|
||||
eval "$3=no"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||
fi
|
||||
eval ac_res=\$$3
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
printf "%s\n" "$ac_res" >&6; }
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
|
||||
} # ac_fn_c_check_header_compile
|
||||
ac_configure_args_raw=
|
||||
for ac_arg
|
||||
do
|
||||
@@ -1684,7 +1678,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by pdfio $as_me 1.7.0, which was
|
||||
It was created by pdfio $as_me 1.5.3, which was
|
||||
generated by GNU Autoconf 2.71. Invocation command line was
|
||||
|
||||
$ $0$ac_configure_args_raw
|
||||
@@ -2440,9 +2434,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
|
||||
|
||||
PDFIO_VERSION="1.7.0"
|
||||
PDFIO_VERSION_MAJOR="`echo 1.7.0 | awk -F. '{print $1}'`"
|
||||
PDFIO_VERSION_MINOR="`echo 1.7.0 | awk -F. '{printf("%d\n",$2);}'`"
|
||||
PDFIO_VERSION="1.5.3"
|
||||
PDFIO_VERSION_MAJOR="`echo 1.5.3 | awk -F. '{print $1}'`"
|
||||
PDFIO_VERSION_MINOR="`echo 1.5.3 | awk -F. '{printf("%d\n",$2);}'`"
|
||||
|
||||
|
||||
|
||||
@@ -3946,43 +3940,6 @@ printf "%s\n" "using $INSTALL" >&6; }
|
||||
|
||||
|
||||
|
||||
ac_header= ac_cache=
|
||||
for ac_item in $ac_header_c_list
|
||||
do
|
||||
if test $ac_cache; then
|
||||
ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
|
||||
if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
|
||||
printf "%s\n" "#define $ac_item 1" >> confdefs.h
|
||||
fi
|
||||
ac_header= ac_cache=
|
||||
elif test $ac_header; then
|
||||
ac_cache=$ac_item
|
||||
else
|
||||
ac_header=$ac_item
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_header_compile "$LINENO" "math.h" "ac_cv_header_math_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_math_h" = xyes
|
||||
then :
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
ac_fn_c_check_func "$LINENO" "timegm" "ac_cv_func_timegm"
|
||||
if test "x$ac_cv_func_timegm" = xyes
|
||||
then :
|
||||
@@ -4144,46 +4101,44 @@ fi
|
||||
PKGCONFIG_CFLAGS="-I\${includedir}"
|
||||
PKGCONFIG_LIBS="-L\${libdir} -lpdfio"
|
||||
PKGCONFIG_LIBS_PRIVATE="-lm"
|
||||
PKGCONFIG_REQUIRES=""
|
||||
PKGCONFIG_REQUIRES_PRIVATE="ttf"
|
||||
PKGCONFIG_REQUIRES="zlib"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ttf library" >&5
|
||||
printf %s "checking for ttf library... " >&6; }
|
||||
|
||||
|
||||
if $PKGCONFIG --exists ttf
|
||||
then :
|
||||
|
||||
# Use installed TTF library...
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
printf "%s\n" "yes" >&6; }
|
||||
CPPFLAGS="$CPPFLAGS $($PKGCONFIG --cflags ttf)"
|
||||
TTFDIR=""
|
||||
LIBS="$($PKGCONFIG --libs ttf) $LIBS"
|
||||
|
||||
else $as_nop
|
||||
|
||||
# Use embedded TTF library...
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using embedded version" >&5
|
||||
printf "%s\n" "no, using embedded version" >&6; }
|
||||
CPPFLAGS="$CPPFLAGS -Ittf"
|
||||
TTFDIR="ttf"
|
||||
LIBS="-Lttf \`PKG_CONFIG_PATH=ttf $PKGCONFIG --libs ttf\` $LIBS"
|
||||
subdirs="$subdirs ttf"
|
||||
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for zlib via pkg-config" >&5
|
||||
printf %s "checking for zlib via pkg-config... " >&6; }
|
||||
ac_header= ac_cache=
|
||||
for ac_item in $ac_header_c_list
|
||||
do
|
||||
if test $ac_cache; then
|
||||
ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
|
||||
if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
|
||||
printf "%s\n" "#define $ac_item 1" >> confdefs.h
|
||||
fi
|
||||
ac_header= ac_cache=
|
||||
elif test $ac_header; then
|
||||
ac_cache=$ac_item
|
||||
else
|
||||
ac_header=$ac_item
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
if $PKGCONFIG --exists zlib
|
||||
then :
|
||||
|
||||
@@ -4191,7 +4146,6 @@ then :
|
||||
printf "%s\n" "yes" >&6; }
|
||||
CPPFLAGS="$($PKGCONFIG --cflags zlib) $CPPFLAGS"
|
||||
LIBS="$($PKGCONFIG --libs zlib) $LIBS"
|
||||
PKGCONFIG_REQUIRES_PRIVATE="$PKGCONFIG_REQUIRES_PRIVATE, zlib"
|
||||
|
||||
else $as_nop
|
||||
|
||||
@@ -4254,6 +4208,7 @@ then :
|
||||
|
||||
fi
|
||||
|
||||
PKGCONFIG_REQUIRES=""
|
||||
PKGCONFIG_LIBS_PRIVATE="-lz $PKGCONFIG_LIBS_PRIVATE"
|
||||
|
||||
fi
|
||||
@@ -4266,6 +4221,9 @@ then :
|
||||
fi
|
||||
|
||||
|
||||
PKGCONFIG_LIBPNG=""
|
||||
|
||||
|
||||
if test "x$PKGCONFIG" != x -a x$enable_libpng != xno
|
||||
then :
|
||||
|
||||
@@ -4281,7 +4239,8 @@ printf "%s\n" "#define HAVE_LIBPNG 1" >>confdefs.h
|
||||
|
||||
CPPFLAGS="$($PKGCONFIG --cflags libpng16) -DHAVE_LIBPNG=1 $CPPFLAGS"
|
||||
LIBS="$($PKGCONFIG --libs libpng16) -lz $LIBS"
|
||||
PKGCONFIG_REQUIRES_PRIVATE="libpng >= 1.6, $PKGCONFIG_REQUIRES_PRIVATE"
|
||||
PKGCONFIG_LIBS_PRIVATE="$($PKGCONFIG --libs libpng16) $PKGCONFIG_LIBS_PRIVATE"
|
||||
PKGCONFIG_REQUIRES="libpng >= 1.6,$PKGCONFIG_REQUIRES"
|
||||
|
||||
else $as_nop
|
||||
|
||||
@@ -4304,51 +4263,6 @@ then :
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --enable-libwebp was given.
|
||||
if test ${enable_libwebp+y}
|
||||
then :
|
||||
enableval=$enable_libwebp;
|
||||
fi
|
||||
|
||||
|
||||
if test "x$PKGCONFIG" != x -a x$enable_libwebp != xno
|
||||
then :
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libwebp" >&5
|
||||
printf %s "checking for libwebp... " >&6; }
|
||||
if $PKGCONFIG --exists libwebp
|
||||
then :
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
printf "%s\n" "yes" >&6; };
|
||||
|
||||
printf "%s\n" "#define HAVE_LIBWEBP 1" >>confdefs.h
|
||||
|
||||
CPPFLAGS="$($PKGCONFIG --cflags libwebp) -DHAVE_LIBWEBP=1 $CPPFLAGS"
|
||||
LIBS="$($PKGCONFIG --libs libwebp) -lz $LIBS"
|
||||
PKGCONFIG_REQUIRES_PRIVATE="libwebp, $PKGCONFIG_REQUIRES_PRIVATE"
|
||||
|
||||
else $as_nop
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
printf "%s\n" "no" >&6; };
|
||||
if test x$enable_libwebp = xyes
|
||||
then :
|
||||
|
||||
as_fn_error $? "libwebp-dev required for --enable-libwebp." "$LINENO" 5
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
elif test x$enable_libwebp = xyes
|
||||
then :
|
||||
|
||||
as_fn_error $? "libwebp-dev required for --enable-libwebp." "$LINENO" 5
|
||||
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --enable-static was given.
|
||||
if test ${enable_static+y}
|
||||
then :
|
||||
@@ -4393,8 +4307,6 @@ else $as_nop
|
||||
LIBPDFIO_STATIC=""
|
||||
PKGCONFIG_LIBS="$PKGCONFIG_LIBS $PKGCONFIG_LIBS_PRIVATE"
|
||||
PKGCONFIG_LIBS_PRIVATE=""
|
||||
PKGCONFIG_REQUIRES="$PKGCONFIG_REQUIRES_PRIVATE"
|
||||
PKGCONFIG_REQUIRES_PRIVATE=""
|
||||
|
||||
fi
|
||||
|
||||
@@ -5187,7 +5099,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by pdfio $as_me 1.7.0, which was
|
||||
This file was extended by pdfio $as_me 1.5.3, which was
|
||||
generated by GNU Autoconf 2.71. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -5243,7 +5155,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config='$ac_cs_config_escaped'
|
||||
ac_cs_version="\\
|
||||
pdfio config.status 1.7.0
|
||||
pdfio config.status 1.5.3
|
||||
configured by $0, generated by GNU Autoconf 2.71,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
@@ -5799,149 +5711,6 @@ if test "$no_create" != yes; then
|
||||
# would make configure fail if this is the last instruction.
|
||||
$ac_cs_success || as_fn_exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# CONFIG_SUBDIRS section.
|
||||
#
|
||||
if test "$no_recursion" != yes; then
|
||||
|
||||
# Remove --cache-file, --srcdir, and --disable-option-checking arguments
|
||||
# so they do not pile up.
|
||||
ac_sub_configure_args=
|
||||
ac_prev=
|
||||
eval "set x $ac_configure_args"
|
||||
shift
|
||||
for ac_arg
|
||||
do
|
||||
if test -n "$ac_prev"; then
|
||||
ac_prev=
|
||||
continue
|
||||
fi
|
||||
case $ac_arg in
|
||||
-cache-file | --cache-file | --cache-fil | --cache-fi \
|
||||
| --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
|
||||
ac_prev=cache_file ;;
|
||||
-cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
|
||||
| --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \
|
||||
| --c=*)
|
||||
;;
|
||||
--config-cache | -C)
|
||||
;;
|
||||
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
|
||||
ac_prev=srcdir ;;
|
||||
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
|
||||
;;
|
||||
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
|
||||
ac_prev=prefix ;;
|
||||
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
|
||||
;;
|
||||
--disable-option-checking)
|
||||
;;
|
||||
*)
|
||||
case $ac_arg in
|
||||
*\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
|
||||
esac
|
||||
as_fn_append ac_sub_configure_args " '$ac_arg'" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Always prepend --prefix to ensure using the same prefix
|
||||
# in subdir configurations.
|
||||
ac_arg="--prefix=$prefix"
|
||||
case $ac_arg in
|
||||
*\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
|
||||
esac
|
||||
ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args"
|
||||
|
||||
# Pass --silent
|
||||
if test "$silent" = yes; then
|
||||
ac_sub_configure_args="--silent $ac_sub_configure_args"
|
||||
fi
|
||||
|
||||
# Always prepend --disable-option-checking to silence warnings, since
|
||||
# different subdirs can have different --enable and --with options.
|
||||
ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args"
|
||||
|
||||
ac_popdir=`pwd`
|
||||
for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue
|
||||
|
||||
# Do not complain, so a configure script can configure whichever
|
||||
# parts of a large source tree are present.
|
||||
test -d "$srcdir/$ac_dir" || continue
|
||||
|
||||
ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)"
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5
|
||||
printf "%s\n" "$ac_msg" >&6
|
||||
as_dir="$ac_dir"; as_fn_mkdir_p
|
||||
ac_builddir=.
|
||||
|
||||
case "$ac_dir" in
|
||||
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
|
||||
*)
|
||||
ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
|
||||
# A ".." for each directory in $ac_dir_suffix.
|
||||
ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
|
||||
case $ac_top_builddir_sub in
|
||||
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
|
||||
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
|
||||
esac ;;
|
||||
esac
|
||||
ac_abs_top_builddir=$ac_pwd
|
||||
ac_abs_builddir=$ac_pwd$ac_dir_suffix
|
||||
# for backward compatibility:
|
||||
ac_top_builddir=$ac_top_build_prefix
|
||||
|
||||
case $srcdir in
|
||||
.) # We are building in place.
|
||||
ac_srcdir=.
|
||||
ac_top_srcdir=$ac_top_builddir_sub
|
||||
ac_abs_top_srcdir=$ac_pwd ;;
|
||||
[\\/]* | ?:[\\/]* ) # Absolute name.
|
||||
ac_srcdir=$srcdir$ac_dir_suffix;
|
||||
ac_top_srcdir=$srcdir
|
||||
ac_abs_top_srcdir=$srcdir ;;
|
||||
*) # Relative name.
|
||||
ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
|
||||
ac_top_srcdir=$ac_top_build_prefix$srcdir
|
||||
ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
|
||||
esac
|
||||
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
|
||||
|
||||
|
||||
cd "$ac_dir"
|
||||
|
||||
# Check for configure.gnu first; this name is used for a wrapper for
|
||||
# Metaconfig's "Configure" on case-insensitive file systems.
|
||||
if test -f "$ac_srcdir/configure.gnu"; then
|
||||
ac_sub_configure=$ac_srcdir/configure.gnu
|
||||
elif test -f "$ac_srcdir/configure"; then
|
||||
ac_sub_configure=$ac_srcdir/configure
|
||||
else
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5
|
||||
printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2;}
|
||||
ac_sub_configure=
|
||||
fi
|
||||
|
||||
# The recursion is here.
|
||||
if test -n "$ac_sub_configure"; then
|
||||
# Make the cache file name correct relative to the subdirectory.
|
||||
case $cache_file in
|
||||
[\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;;
|
||||
*) # Relative name.
|
||||
ac_sub_cache_file=$ac_top_build_prefix$cache_file ;;
|
||||
esac
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5
|
||||
printf "%s\n" "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;}
|
||||
# The eval makes quoting arguments work.
|
||||
eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \
|
||||
--cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" ||
|
||||
as_fn_error $? "$ac_sub_configure failed for $ac_dir" "$LINENO" 5
|
||||
fi
|
||||
|
||||
cd "$ac_popdir"
|
||||
done
|
||||
fi
|
||||
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
|
||||
printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
|
||||
|
||||
65
configure.ac
@@ -1,7 +1,7 @@
|
||||
dnl
|
||||
dnl Configuration script for PDFio
|
||||
dnl
|
||||
dnl Copyright © 2023-2026 by Michael R Sweet
|
||||
dnl Copyright © 2023-2025 by Michael R Sweet
|
||||
dnl
|
||||
dnl Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
dnl information.
|
||||
@@ -21,7 +21,7 @@ AC_PREREQ([2.70])
|
||||
|
||||
|
||||
dnl Package name and version...
|
||||
AC_INIT([pdfio], [1.7.0], [https://github.com/michaelrsweet/pdfio/issues], [pdfio], [https://www.msweet.org/pdfio])
|
||||
AC_INIT([pdfio], [1.5.3], [https://github.com/michaelrsweet/pdfio/issues], [pdfio], [https://www.msweet.org/pdfio])
|
||||
|
||||
PDFIO_VERSION="AC_PACKAGE_VERSION"
|
||||
PDFIO_VERSION_MAJOR="`echo AC_PACKAGE_VERSION | awk -F. '{print $1}'`"
|
||||
@@ -88,10 +88,6 @@ AC_SUBST([INSTALL])
|
||||
AC_MSG_RESULT([using $INSTALL])
|
||||
|
||||
|
||||
dnl Standard C stuff...
|
||||
AC_CHECK_HEADER([math.h])
|
||||
|
||||
|
||||
dnl Check for date/time functionality...
|
||||
AC_CHECK_FUNC([timegm], [
|
||||
AC_DEFINE([HAVE_TIMEGM], [1], [Do we have the timegm function?])
|
||||
@@ -119,32 +115,11 @@ AC_PATH_TOOL([PKGCONFIG], [pkg-config])
|
||||
PKGCONFIG_CFLAGS="-I\${includedir}"
|
||||
PKGCONFIG_LIBS="-L\${libdir} -lpdfio"
|
||||
PKGCONFIG_LIBS_PRIVATE="-lm"
|
||||
PKGCONFIG_REQUIRES=""
|
||||
PKGCONFIG_REQUIRES_PRIVATE="ttf"
|
||||
PKGCONFIG_REQUIRES="zlib"
|
||||
AC_SUBST([PKGCONFIG_CFLAGS])
|
||||
AC_SUBST([PKGCONFIG_LIBS])
|
||||
AC_SUBST([PKGCONFIG_LIBS_PRIVATE])
|
||||
AC_SUBST([PKGCONFIG_REQUIRES])
|
||||
AC_SUBST([PKGCONFIG_REQUIRES_PRIVATE])
|
||||
|
||||
|
||||
dnl TTF library for font support...
|
||||
AC_MSG_CHECKING([for ttf library])
|
||||
AS_IF([$PKGCONFIG --exists ttf], [
|
||||
# Use installed TTF library...
|
||||
AC_MSG_RESULT([yes])
|
||||
CPPFLAGS="$CPPFLAGS $($PKGCONFIG --cflags ttf)"
|
||||
TTFDIR=""
|
||||
LIBS="$($PKGCONFIG --libs ttf) $LIBS"
|
||||
], [
|
||||
# Use embedded TTF library...
|
||||
AC_MSG_RESULT([no, using embedded version])
|
||||
CPPFLAGS="$CPPFLAGS -Ittf"
|
||||
TTFDIR="ttf"
|
||||
LIBS="-Lttf \`PKG_CONFIG_PATH=ttf $PKGCONFIG --libs ttf\` $LIBS"
|
||||
AC_CONFIG_SUBDIRS([ttf])
|
||||
])
|
||||
AC_SUBST([TTFDIR])
|
||||
|
||||
|
||||
dnl ZLIB
|
||||
@@ -153,7 +128,6 @@ AS_IF([$PKGCONFIG --exists zlib], [
|
||||
AC_MSG_RESULT([yes])
|
||||
CPPFLAGS="$($PKGCONFIG --cflags zlib) $CPPFLAGS"
|
||||
LIBS="$($PKGCONFIG --libs zlib) $LIBS"
|
||||
PKGCONFIG_REQUIRES_PRIVATE="$PKGCONFIG_REQUIRES_PRIVATE, zlib"
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
AC_CHECK_HEADER([zlib.h])
|
||||
@@ -163,12 +137,16 @@ AS_IF([$PKGCONFIG --exists zlib], [
|
||||
AC_MSG_ERROR([Sorry, this software requires zlib 1.1 or higher.])
|
||||
])
|
||||
|
||||
PKGCONFIG_REQUIRES=""
|
||||
PKGCONFIG_LIBS_PRIVATE="-lz $PKGCONFIG_LIBS_PRIVATE"
|
||||
])
|
||||
|
||||
|
||||
dnl libpng...
|
||||
AC_ARG_ENABLE([libpng], AS_HELP_STRING([--disable-libpng], [use libpng for pdfioFileCreateImageObjFromFile, default=auto]))
|
||||
AC_ARG_ENABLE([libpng], AS_HELP_STRING([--enable-libpng], [use libpng for pdfioFileCreateImageObjFromFile, default=auto]))
|
||||
|
||||
PKGCONFIG_LIBPNG=""
|
||||
AC_SUBST([PKGCONFIG_LIBPNG])
|
||||
|
||||
AS_IF([test "x$PKGCONFIG" != x -a x$enable_libpng != xno], [
|
||||
AC_MSG_CHECKING([for libpng-1.6.x])
|
||||
@@ -177,7 +155,8 @@ AS_IF([test "x$PKGCONFIG" != x -a x$enable_libpng != xno], [
|
||||
AC_DEFINE([HAVE_LIBPNG], 1, [Have PNG library?])
|
||||
CPPFLAGS="$($PKGCONFIG --cflags libpng16) -DHAVE_LIBPNG=1 $CPPFLAGS"
|
||||
LIBS="$($PKGCONFIG --libs libpng16) -lz $LIBS"
|
||||
PKGCONFIG_REQUIRES_PRIVATE="libpng >= 1.6, $PKGCONFIG_REQUIRES_PRIVATE"
|
||||
PKGCONFIG_LIBS_PRIVATE="$($PKGCONFIG --libs libpng16) $PKGCONFIG_LIBS_PRIVATE"
|
||||
PKGCONFIG_REQUIRES="libpng >= 1.6,$PKGCONFIG_REQUIRES"
|
||||
], [
|
||||
AC_MSG_RESULT([no]);
|
||||
AS_IF([test x$enable_libpng = xyes], [
|
||||
@@ -189,28 +168,6 @@ AS_IF([test "x$PKGCONFIG" != x -a x$enable_libpng != xno], [
|
||||
])
|
||||
|
||||
|
||||
dnl libwebp...
|
||||
AC_ARG_ENABLE([libwebp], AS_HELP_STRING([--disable-libwebp], [use libwebp for pdfioFileCreateImageObjFromFile, default=auto]))
|
||||
|
||||
AS_IF([test "x$PKGCONFIG" != x -a x$enable_libwebp != xno], [
|
||||
AC_MSG_CHECKING([for libwebp])
|
||||
AS_IF([$PKGCONFIG --exists libwebp], [
|
||||
AC_MSG_RESULT([yes]);
|
||||
AC_DEFINE([HAVE_LIBWEBP], 1, [Have WebP library?])
|
||||
CPPFLAGS="$($PKGCONFIG --cflags libwebp) -DHAVE_LIBWEBP=1 $CPPFLAGS"
|
||||
LIBS="$($PKGCONFIG --libs libwebp) -lz $LIBS"
|
||||
PKGCONFIG_REQUIRES_PRIVATE="libwebp, $PKGCONFIG_REQUIRES_PRIVATE"
|
||||
], [
|
||||
AC_MSG_RESULT([no]);
|
||||
AS_IF([test x$enable_libwebp = xyes], [
|
||||
AC_MSG_ERROR([libwebp-dev required for --enable-libwebp.])
|
||||
])
|
||||
])
|
||||
], [test x$enable_libwebp = xyes], [
|
||||
AC_MSG_ERROR([libwebp-dev required for --enable-libwebp.])
|
||||
])
|
||||
|
||||
|
||||
dnl Library target...
|
||||
AC_ARG_ENABLE([static], AS_HELP_STRING([--disable-static], [do not install static library]))
|
||||
AC_ARG_ENABLE([shared], AS_HELP_STRING([--enable-shared], [install shared library]))
|
||||
@@ -232,8 +189,6 @@ AS_IF([test x$enable_shared = xyes], [
|
||||
LIBPDFIO_STATIC=""
|
||||
PKGCONFIG_LIBS="$PKGCONFIG_LIBS $PKGCONFIG_LIBS_PRIVATE"
|
||||
PKGCONFIG_LIBS_PRIVATE=""
|
||||
PKGCONFIG_REQUIRES="$PKGCONFIG_REQUIRES_PRIVATE"
|
||||
PKGCONFIG_REQUIRES_PRIVATE=""
|
||||
])
|
||||
|
||||
AC_SUBST([LIBPDFIO])
|
||||
|
||||
561
doc/pdfio.3
@@ -1,4 +1,4 @@
|
||||
.TH pdfio 3 "pdf read/write library" "2026-02-04" "pdf read/write library"
|
||||
.TH pdfio 3 "pdf read/write library" "2025-05-03" "pdf read/write library"
|
||||
.SH NAME
|
||||
pdfio \- pdf read/write library
|
||||
.SH Introduction
|
||||
@@ -34,7 +34,7 @@ PDFio is
|
||||
.I not
|
||||
concerned with rendering or viewing a PDF file, although a PDF RIP or viewer could be written using it.
|
||||
.PP
|
||||
Copyright \[co] 2021\-2026 by Michael R Sweet. PDFio is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GNU GPL2\-only software. See the files LICENSE and NOTICE for more information.
|
||||
PDFio is Copyright \[co] 2021\-2025 by Michael R Sweet and is licensed under the Apache License Version 2.0 with an (optional) exception to allow linking against GPL2/LGPL2 software. See the files "LICENSE" and "NOTICE" for more information.
|
||||
.SS Requirements
|
||||
.PP
|
||||
PDFio requires the following to build the software:
|
||||
@@ -52,26 +52,14 @@ A POSIX\-compliant sh program
|
||||
|
||||
.IP \(bu 5
|
||||
.PP
|
||||
libpng (https://www.libpng.org/) 1.6 or later for full PNG image support (optional)
|
||||
ZLIB (https://www.zlib.net/) 1.0 or higher
|
||||
|
||||
|
||||
.IP \(bu 5
|
||||
.PP
|
||||
libwebp (https://developers.google.com/speed/webp) 1.0 or later for WebP image support (optional)
|
||||
|
||||
.IP \(bu 5
|
||||
.PP
|
||||
ZLIB (https://www.zlib.net/) 1.1 or later for compression support
|
||||
|
||||
|
||||
PDFio will also use libpng 1.6 or higher (https://www.libpng.org/) to provide enhanced PNG image support.
|
||||
.PP
|
||||
IDE files for Xcode (macOS/iOS) and Visual Studio (Windows) are also provided.
|
||||
.PP
|
||||
On a stock Ubuntu install, the following command will install the various prerequisites:
|
||||
.nf
|
||||
|
||||
sudo apt\-get install build\-essential libpng\-dev libwebp\-dev zlib1g\-dev
|
||||
.fi
|
||||
.SS Building and Installing PDFio on Linux/Unix
|
||||
.SS Installing PDFio
|
||||
.PP
|
||||
PDFio comes with a configure script that creates a portable makefile that will work on any POSIX\-compliant system with ZLIB installed. To make it, run:
|
||||
.nf
|
||||
@@ -111,22 +99,16 @@ Other configure options can be found using the \-\-help option:
|
||||
|
||||
\./configure \-\-help
|
||||
.fi
|
||||
.SS Building on Windows with Visual Studio
|
||||
.SS Visual Studio Project
|
||||
.PP
|
||||
The Visual Studio solution ("pdfio.sln") is provided for Windows developers and generates the PDFIO1 DLL. You can also use NuGet to install the pdfio_native package.
|
||||
The Visual Studio solution ("pdfio.sln") is provided for Windows developers and generates both a static library and DLL.
|
||||
.SS Xcode Project
|
||||
.PP
|
||||
You can build and run the testpdfio unit tests target from within Visual Studio to verify the functioning of the library.
|
||||
.SS Building on macOS with Xcode
|
||||
.PP
|
||||
The Xcode project (pdfio.xcodeproj) is provided for macOS developer which generates a static library that will be installed under "/usr/local". Run the following command to build and install PDFio on macOS:
|
||||
There is also an Xcode project ("pdfio.xcodeproj") you can use on macOS which generates a static library that will be installed under "/usr/local" with:
|
||||
.nf
|
||||
|
||||
sudo xcodebuild install
|
||||
.fi
|
||||
.PP
|
||||
Alternately you can add the Xcode project to a workspace and reference the PDFio library target as a dependency in your own project.
|
||||
.PP
|
||||
You can build and run the testpdfio unit tests target from within Xcode to verify the functioning of the library.
|
||||
.SS Detecting PDFio
|
||||
.PP
|
||||
PDFio can be detected using the pkg\-config command, for example:
|
||||
@@ -379,28 +361,41 @@ Each PDF file contains one or more pages. The pdfioFileGetNumPages function retu
|
||||
}
|
||||
.fi
|
||||
.PP
|
||||
Each page is represented by a "page tree" object (what pdfioFileGetPage returns) that specifies information about the page and one or more "content" objects that contain the images, fonts, text, and graphics that appear on the page. Use the pdfioPageGetNumStreams and pdfioPageOpenStream functions to access the content streams for each page, pdfioObjGetDict to get the associated page object dictionary, and pdfioPageGetArray, pdfioPageGetBinary, pdfioPageGetBoolean, pdfioPageGetDate, pdfioPageGetDict, pdfioPageGetName, pdfioPageGetObj, pdfioPageGetRect, and pdfioPageGetString to get a value from the page object dictionary or its parents. For example, if you want to display the media and crop boxes for a given page:
|
||||
Each page is represented by a "page tree" object (what pdfioFileGetPage returns) that specifies information about the page and one or more "content" objects that contain the images, fonts, text, and graphics that appear on the page. Use the pdfioPageGetNumStreams and pdfioPageOpenStream functions to access the content streams for each page, and pdfioObjGetDict to get the associated page object dictionary. For example, if you want to display the media and crop boxes for a given page:
|
||||
.nf
|
||||
|
||||
pdfio_file_t *pdf; // PDF file
|
||||
size_t i; // Looping var
|
||||
size_t count; // Number of pages
|
||||
pdfio_obj_t *page; // Current page
|
||||
pdfio_rect_t media_box; // MediaBox values
|
||||
pdfio_rect_t crop_box; // CropBox values
|
||||
pdfio_dict_t *dict; // Current page dictionary
|
||||
pdfio_array_t *media_box; // MediaBox array
|
||||
double media_values[4]; // MediaBox values
|
||||
pdfio_array_t *crop_box; // CropBox array
|
||||
double crop_values[4]; // CropBox values
|
||||
|
||||
// Iterate the pages in the PDF file
|
||||
for (i = 0, count = pdfioFileGetNumPages(pdf); i < count; i ++)
|
||||
{
|
||||
page = pdfioFileGetPage(pdf, i);
|
||||
dict = pdfioObjGetDict(page);
|
||||
|
||||
pdfioPageGetRect(page, "MediaBox", &media_box);
|
||||
pdfioPageGetRect(page, "CropBox", &crop_box);
|
||||
media_box = pdfioDictGetArray(dict, "MediaBox");
|
||||
media_values[0] = pdfioArrayGetNumber(media_box, 0);
|
||||
media_values[1] = pdfioArrayGetNumber(media_box, 1);
|
||||
media_values[2] = pdfioArrayGetNumber(media_box, 2);
|
||||
media_values[3] = pdfioArrayGetNumber(media_box, 3);
|
||||
|
||||
crop_box = pdfioDictGetArray(dict, "CropBox");
|
||||
crop_values[0] = pdfioArrayGetNumber(crop_box, 0);
|
||||
crop_values[1] = pdfioArrayGetNumber(crop_box, 1);
|
||||
crop_values[2] = pdfioArrayGetNumber(crop_box, 2);
|
||||
crop_values[3] = pdfioArrayGetNumber(crop_box, 3);
|
||||
|
||||
printf("Page %u: MediaBox=[%g %g %g %g], CropBox=[%g %g %g %g]\\n",
|
||||
(unsigned)(i + 1),
|
||||
media_box.x1, media_box.y1, media_box.x2, media_box.y2,
|
||||
crop_box.x1, crop_box.y1, crop_box.x2, crop_box.y2);
|
||||
media_values[0], media_values[1], media_values[2], media_values[3],
|
||||
crop_values[0], crop_values[1], crop_values[2], crop_values[3]);
|
||||
}
|
||||
.fi
|
||||
.PP
|
||||
@@ -789,13 +784,16 @@ will create an object for a 1024x1024 RGBA image in memory, using the default co
|
||||
.PP
|
||||
The "interpolate" argument specifies whether the colors in the image should be smoothed/interpolated when scaling. This is most useful for photographs but should be false for screenshot and barcode images.
|
||||
.PP
|
||||
If you have a GIF, JPEG, PNG, or WebP file, use the pdfioFileCreateImageObjFromFile function to copy the image into a PDF image object, for example:
|
||||
If you have a JPEG or PNG file, use the pdfioFileCreateImageObjFromFile function to copy the image into a PDF image object, for example:
|
||||
.nf
|
||||
|
||||
pdfio_file_t *pdf = pdfioFileCreate(...);
|
||||
pdfio_obj_t *img =
|
||||
pdfioFileCreateImageObjFromFile(pdf, "myphoto.jpg", /*interpolate*/true);
|
||||
.fi
|
||||
.PP
|
||||
Note: Currently pdfioFileCreateImageObjFromFile does not support 12 bit JPEG files or PNG files with an alpha channel.
|
||||
|
||||
.PP
|
||||
Page Dictionary Functions
|
||||
.PP
|
||||
@@ -1034,45 +1032,6 @@ pdfioContentTextShowf draws a formatted string in a text block
|
||||
pdfioContentTextShowJustified draws an array of literal strings with offsets between them
|
||||
|
||||
|
||||
.SS Tagged and Marked PDF Content
|
||||
.PP
|
||||
Content in a page stream can be tagged to help a PDF reader application know the kind and organization of that content. Content inserted using the PDFio Page Stream Functions can be tagged by surrounding it with the pdfioContentBeginMarked and pdfioContentEndMarked functions.
|
||||
.PP
|
||||
The pdfioContentBeginMarked function accepts a named tag and optional dictionary of attributes such as the marked content identifier ("MCID"). For example, the following code tags a paragraph of text:
|
||||
.nf
|
||||
|
||||
pdfio_file_t *pdf; // PDF file
|
||||
pdfio_stream_t *st; // Page stream
|
||||
|
||||
pdfioContentBeginMarked(st, "P", /*dict*/NULL);
|
||||
|
||||
pdfioContentTextShow(st, /*unicode*/false, "Mary had a little lamb\\n");
|
||||
pdfioContentTextShow(st, /*unicode*/false, "whose fleece was white as snow.\\n");
|
||||
pdfioContentTextShow(st, /*unicode*/false, "And everywhere that Mary went\\n");
|
||||
pdfioContentTextShow(st, /*unicode*/false, "the lamb was sure to go,\\n");
|
||||
|
||||
pdfioContentEndMarked(st);
|
||||
.fi
|
||||
.PP
|
||||
To mark the same paragraph with a content identifier you would first create a dictionary containing the "MCID" key/value pair and then mark the paragraph with that dictionary:
|
||||
.nf
|
||||
|
||||
pdfio_file_t *pdf; // PDF file
|
||||
pdfio_stream_t *st; // Page stream
|
||||
pdfio_dict_t *dict; // Content dictionary
|
||||
|
||||
dict = pdfioDictCreate(pdf);
|
||||
pdfioDictSetNumber(dict, "MCID", 42);
|
||||
|
||||
pdfioContentBeginMarked(st, "P", dict);
|
||||
|
||||
pdfioContentTextShow(st, /*unicode*/false, "Mary had a little lamb\\n");
|
||||
pdfioContentTextShow(st, /*unicode*/false, "whose fleece was white as snow.\\n");
|
||||
pdfioContentTextShow(st, /*unicode*/false, "And everywhere that Mary went\\n");
|
||||
pdfioContentTextShow(st, /*unicode*/false, "the lamb was sure to go,\\n");
|
||||
|
||||
pdfioContentEndMarked(st);
|
||||
.fi
|
||||
.SH Examples
|
||||
.PP
|
||||
PDFio includes several example programs that are typically installed to the /usr/share/doc/pdfio/examples or /usr/local/share/doc/pdfio/examples directories. A makefile is included to build them.
|
||||
@@ -1178,10 +1137,16 @@ The pdfioinfo.c example program opens a PDF file and prints the title, author, c
|
||||
for (cur = 0, prev = 0; cur < num_pages; cur ++)
|
||||
{
|
||||
// Find the MediaBox for this page in the page tree...
|
||||
page = pdfioFileGetPage(pdf, cur);
|
||||
for (page = pdfioFileGetPage(pdf, cur);
|
||||
page != NULL;
|
||||
page = pdfioDictGetObj(page_dict, "Parent"))
|
||||
{
|
||||
cur_box.x1 = cur_box.x2 = cur_box.y1 = cur_box.y2 = 0.0;
|
||||
page_dict = pdfioObjGetDict(page);
|
||||
|
||||
cur_box.x1 = cur_box.x2 = cur_box.y1 = cur_box.y2 = 0.0;
|
||||
pdfioPageGetRect(page, "MediaBox", &cur_box);
|
||||
if (pdfioDictGetRect(page_dict, "MediaBox", &cur_box))
|
||||
break;
|
||||
}
|
||||
|
||||
// If this MediaBox is different from the previous one, show the range of
|
||||
// pages that have that size...
|
||||
@@ -1454,7 +1419,7 @@ Then we loop through the differences array, keeping track of the current index w
|
||||
.fi
|
||||
.SS Create a PDF File With Text and an Image
|
||||
.PP
|
||||
The image2pdf.c example code creates a PDF file containing a GIF, JPEG, or PNG image file and optional caption on a single page. The create_pdf_image_file function creates the PDF file, embeds a base font and the named JPEG or PNG image file, and then creates a page with the image centered on the page with any text centered below:
|
||||
The image2pdf.c example code creates a PDF file containing a JPEG or PNG image file and optional caption on a single page. The create_pdf_image_file function creates the PDF file, embeds a base font and the named JPEG or PNG image file, and then creates a page with the image centered on the page with any text centered below:
|
||||
.nf
|
||||
|
||||
#include <pdfio.h>
|
||||
@@ -1726,9 +1691,6 @@ The md2pdf program needs to maintain three sets of state \- one for the markdown
|
||||
// State for the current page
|
||||
pdfio_stream_t *st; // Current page stream
|
||||
double y; // Current position on page
|
||||
const char *tag; // Current block tag
|
||||
bool in_table, // Are we in a table?
|
||||
in_row; // Are we in a table row?
|
||||
docfont_t font; // Current font
|
||||
double fsize; // Current font size
|
||||
doccolor_t color; // Current color
|
||||
@@ -2205,9 +2167,6 @@ Code blocks consist of one or more lines of plain monospaced text. We draw a lig
|
||||
pdfioContentFillAndStroke(dd\->st, false);
|
||||
|
||||
// Start a code text block...
|
||||
dd\->tag = "P";
|
||||
pdfioContentBeginMarked(dd\->st, dd\->tag, /*dict*/NULL);
|
||||
|
||||
set_font(dd, DOCFONT_MONOSPACE, SIZE_CODEBLOCK);
|
||||
pdfioContentTextBegin(dd\->st);
|
||||
pdfioContentTextMoveTo(dd\->st, left, dd\->y);
|
||||
@@ -2244,9 +2203,6 @@ Code blocks consist of one or more lines of plain monospaced text. We draw a lig
|
||||
pdfioContentTextEnd(dd\->st);
|
||||
dd\->y += lineheight;
|
||||
|
||||
pdfioContentEndMarked(dd\->st);
|
||||
dd\->tag = NULL;
|
||||
|
||||
// Draw the bottom padding...
|
||||
set_color(dd, DOCCOLOR_LTGRAY);
|
||||
pdfioContentPathRect(dd\->st, left \- CODE_PADDING,
|
||||
@@ -2376,17 +2332,8 @@ Finally, we render each row in the table:
|
||||
.nf
|
||||
|
||||
// Render each table row...
|
||||
dd\->in_table = true;
|
||||
|
||||
if (dd\->st)
|
||||
pdfioContentBeginMarked(dd\->st, "Table", /*dict*/NULL);
|
||||
|
||||
for (row = 0, rowptr = rows; row < num_rows; row ++, rowptr ++)
|
||||
render_row(dd, num_cols, cols, rowptr);
|
||||
|
||||
pdfioContentEndMarked(dd\->st);
|
||||
|
||||
dd\->in_table = false;
|
||||
.fi
|
||||
.PP
|
||||
Rendering the Markdown Document
|
||||
@@ -2505,10 +2452,6 @@ PDFIO_CS_ADOBE
|
||||
.br
|
||||
AdobeRGB 1998
|
||||
.TP 5
|
||||
PDFIO_CS_CGATS001
|
||||
.br
|
||||
CGATS001 (CMYK)
|
||||
.TP 5
|
||||
PDFIO_CS_P3_D65
|
||||
.br
|
||||
Display P3
|
||||
@@ -2551,7 +2494,7 @@ ASCIIHexDecode filter (reading only)
|
||||
.TP 5
|
||||
PDFIO_FILTER_CCITTFAX
|
||||
.br
|
||||
CCITTFaxDecode filter (reading only)
|
||||
CCITTFaxDecode filter
|
||||
.TP 5
|
||||
PDFIO_FILTER_CRYPT
|
||||
.br
|
||||
@@ -2567,7 +2510,7 @@ FlateDecode filter
|
||||
.TP 5
|
||||
PDFIO_FILTER_JBIG2
|
||||
.br
|
||||
JBIG2Decode filter (reading only)
|
||||
JBIG2Decode filter
|
||||
.TP 5
|
||||
PDFIO_FILTER_JPX
|
||||
.br
|
||||
@@ -2898,8 +2841,7 @@ pdfio_array_t * pdfioArrayCreateColorFromStandard (
|
||||
.fi
|
||||
.PP
|
||||
This function creates a color array for a standard \fBPDFIO_CS_\fR enumerated color space.
|
||||
The "num_colors" argument must be \fB1\fR for grayscale, \fB3\fR for RGB color, and
|
||||
\fB4\fR for CMYK color.
|
||||
The "num_colors" argument must be \fB1\fR for grayscale and \fB3\fR for RGB color.
|
||||
.SS pdfioArrayGetArray
|
||||
Get an array value from an array.
|
||||
.PP
|
||||
@@ -3010,30 +2952,6 @@ bool pdfioArrayRemove (
|
||||
.fi
|
||||
.PP
|
||||
|
||||
.SS pdfioContentBeginMarked
|
||||
Start marked content with an optional dictionary.
|
||||
.PP
|
||||
.nf
|
||||
bool pdfioContentBeginMarked (
|
||||
pdfio_stream_t *st,
|
||||
const char *tag,
|
||||
pdfio_dict_t *dict
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function starts an area of marked content with an optional dictionary.
|
||||
It must be paired with a call to the \fIpdfioContentEndMarked\fR function.
|
||||
.PP
|
||||
The "tag" argument specifies the tag name string for the content such as "P"
|
||||
for a paragraph, "H1" for a top-level heading, and so forth. The "dict"
|
||||
argument specifies an optional dictionary of properties for the content such
|
||||
as the marked content identifier ("MCID") number.
|
||||
.PP
|
||||
Calling this function sets the "Marked" key in the "MarkInfo" dictionary of
|
||||
the document catalog. The caller is responsible for setting the
|
||||
"StructTreeRoot" dictionary when creating marked content.
|
||||
|
||||
|
||||
.SS pdfioContentClip
|
||||
Clip output to the current path.
|
||||
.PP
|
||||
@@ -3059,19 +2977,6 @@ bool pdfioContentDrawImage (
|
||||
.PP
|
||||
The object name must be part of the page dictionary resources, typically
|
||||
using the \fIpdfioPageDictAddImage\fR function.
|
||||
.SS pdfioContentEndMarked
|
||||
End marked content.
|
||||
.PP
|
||||
.nf
|
||||
bool pdfioContentEndMarked (
|
||||
pdfio_stream_t *st
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function ends an area of marked content that was started using the
|
||||
\fIpdfioContentBeginMarked\fR function.
|
||||
|
||||
|
||||
.SS pdfioContentFill
|
||||
Fill the current path.
|
||||
.PP
|
||||
@@ -3936,39 +3841,6 @@ bool pdfioDictSetStringf (
|
||||
...
|
||||
);
|
||||
.fi
|
||||
.SS pdfioFileAddOutputIntent
|
||||
Add an OutputIntent to a file.
|
||||
.PP
|
||||
.nf
|
||||
void pdfioFileAddOutputIntent (
|
||||
pdfio_file_t *pdf,
|
||||
const char *subtype,
|
||||
const char *condition,
|
||||
const char *cond_id,
|
||||
const char *reg_name,
|
||||
const char *info,
|
||||
pdfio_obj_t *profile
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function adds an OutputIntent dictionary to the PDF file catalog.
|
||||
The "subtype" argument specifies the intent subtype and is typically
|
||||
"GTS_PDFX" for PDF/X, "GTS_PDFA1" for PDF/A, or "ISO_PDFE1" for PDF/E.
|
||||
Passing \fBNULL\fR defaults the subtype to "GTS_PDFA1".
|
||||
.PP
|
||||
The "condition" argument specifies a short name for the output intent, while
|
||||
the "info" argument specifies a longer description for the output intent.
|
||||
Both can be \fBNULL\fR to omit this information.
|
||||
.PP
|
||||
The "cond_id" argument specifies a unique identifier such as a registration
|
||||
("CGATS001") or color space name ("sRGB"). The "reg_name" argument provides
|
||||
a URL for the identifier.
|
||||
.PP
|
||||
The "profile" argument specifies an ICC profile object for the output
|
||||
condition. If \fBNULL\fR, the PDF consumer will attempt to look up the correct
|
||||
profile using the "cond_id" value.
|
||||
|
||||
|
||||
.SS pdfioFileClose
|
||||
Close a PDF file and free all memory used for it.
|
||||
.PP
|
||||
@@ -3995,31 +3867,8 @@ This function creates a new PDF file. The "filename" argument specifies the
|
||||
name of the PDF file to create.
|
||||
.PP
|
||||
The "version" argument specifies the PDF version number for the file or
|
||||
\fBNULL\fR for the default ("2.0"). The following values are recognized:
|
||||
.PP
|
||||
.IP \(bu 5
|
||||
"1.3", "1.4", "1.5", "1.6", "1.7", "2.0": Generic PDF files of the
|
||||
specified versions.
|
||||
.IP \(bu 5
|
||||
"PCLm-1.0": The PCLm (raster) subset of PDF supported by some printers.
|
||||
.IP \(bu 5
|
||||
"PDF/A-1a": PDF/A-1a:2005
|
||||
.IP \(bu 5
|
||||
"PDF/A-1b": PDF/A-1b:2005
|
||||
.IP \(bu 5
|
||||
"PDF/A-2a": PDF/A-2a:2011
|
||||
.IP \(bu 5
|
||||
"PDF/A-2b": PDF/A-2b:2011
|
||||
.IP \(bu 5
|
||||
"PDF/A-2u": PDF/A-2u:2011
|
||||
.IP \(bu 5
|
||||
"PDF/A-3a": PDF/A-3a:2012
|
||||
.IP \(bu 5
|
||||
"PDF/A-3b": PDF/A-3b:2012
|
||||
.IP \(bu 5
|
||||
"PDF/A-3u": PDF/A-3u:2012
|
||||
.IP \(bu 5
|
||||
"PDF/A-4": PDF/A-4:2020
|
||||
\fBNULL\fR for the default ("2.0"). The value "PCLm-1.0" can be specified to
|
||||
produce the PCLm subset of PDF.
|
||||
.PP
|
||||
The "media_box" and "crop_box" arguments specify the default MediaBox and
|
||||
CropBox for pages in the PDF file - if \fBNULL\fR then a default "Universal" size
|
||||
@@ -4027,24 +3876,8 @@ of 8.27x11in (the intersection of US Letter and ISO A4) is used.
|
||||
.PP
|
||||
The "error_cb" and "error_cbdata" arguments specify an error handler callback
|
||||
and its data pointer - if \fBNULL\fR then the default error handler is used that
|
||||
writes error and warning messages to \fBstderr\fR. The error handler callback
|
||||
should return \fBtrue\fR to continue writing the PDF file or \fBfalse\fR to stop.
|
||||
For example:
|
||||
.PP
|
||||
.nf
|
||||
bool
|
||||
my_error_cb(pdfio_file_t *pdf, const char *message, void *data)
|
||||
{
|
||||
(void)data; /* Not using data pointer in this callback */
|
||||
|
||||
fprintf(stderr, "%s: %sn", pdfioFileGetName(pdf), message);
|
||||
|
||||
/* Return true to continue on warning messages, false otherwise... */
|
||||
return (!strncmp(message, "WARNING:", 8));
|
||||
}
|
||||
|
||||
.fi
|
||||
|
||||
writes error messages to \fBstderr\fR. The error handler callback should return
|
||||
\fBtrue\fR to continue writing the PDF file or \fBfalse\fR to stop.
|
||||
.SS pdfioFileCreateArrayObj
|
||||
Create a new object in a PDF file containing an array.
|
||||
.PP
|
||||
@@ -4102,30 +3935,8 @@ specifies the font nane:
|
||||
Aside from "Symbol" and "Zapf-Dingbats", Base fonts use the Windows CP1252
|
||||
(ISO-8859-1 with additional characters such as the Euro symbol) subset of
|
||||
Unicode.
|
||||
.PP
|
||||
.IP 5
|
||||
Note: This function cannot be used when producing PDF/A files.
|
||||
.SS pdfioFileCreateFontObjFromData
|
||||
Add a font in memory to a PDF file.
|
||||
.PP
|
||||
.nf
|
||||
pdfio_obj_t * pdfioFileCreateFontObjFromData (
|
||||
pdfio_file_t *pdf,
|
||||
const void *data,
|
||||
size_t datasize,
|
||||
bool unicode
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function embeds TrueType/OpenType font data into a PDF file. The
|
||||
"unicode" parameter controls whether the font is encoded for two-byte
|
||||
characters (potentially full Unicode, but more typically a subset)
|
||||
or to only support the Windows CP1252 (ISO-8859-1 with additional
|
||||
characters such as the Euro symbol) subset of Unicode.
|
||||
|
||||
|
||||
.SS pdfioFileCreateFontObjFromFile
|
||||
Add a font file to a PDF file.
|
||||
Add a font object to a PDF file.
|
||||
.PP
|
||||
.nf
|
||||
pdfio_obj_t * pdfioFileCreateFontObjFromFile (
|
||||
@@ -4135,7 +3946,7 @@ pdfio_obj_t * pdfioFileCreateFontObjFromFile (
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function embeds a TrueType/OpenType font file into a PDF file. The
|
||||
This function embeds a TrueType/OpenType font into a PDF file. The
|
||||
"unicode" parameter controls whether the font is encoded for two-byte
|
||||
characters (potentially full Unicode, but more typically a subset)
|
||||
or to only support the Windows CP1252 (ISO-8859-1 with additional
|
||||
@@ -4188,12 +3999,8 @@ the image is encoded in the corresponding device color space. The
|
||||
"interpolate" parameter specifies whether to interpolate when scaling the
|
||||
image on the page.
|
||||
.PP
|
||||
.IP 5
|
||||
Note: When creating an image object with alpha, a second image object is
|
||||
.IP 5
|
||||
created to hold the "soft mask" data for the primary image. PDF/A-1
|
||||
.IP 5
|
||||
files do not support alpha-based transparency.
|
||||
created to hold the "soft mask" data for the primary image.
|
||||
.SS pdfioFileCreateImageObjFromFile
|
||||
Add an image object to a PDF file from a file.
|
||||
.PP
|
||||
@@ -4205,21 +4012,17 @@ pdfio_obj_t * pdfioFileCreateImageObjFromFile (
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function creates an image object in a PDF file from a GIF, JPEG, PNG, or
|
||||
WebP file. The "filename" parameter specifies the name of the GIF, JPEG,
|
||||
PNG, or WebP file, while the "interpolate" parameter specifies whether to
|
||||
interpolate when scaling the image on the page.
|
||||
This function creates an image object in a PDF file from a JPEG or PNG file.
|
||||
The "filename" parameter specifies the name of the JPEG or PNG file, while
|
||||
the "interpolate" parameter specifies whether to interpolate when scaling the
|
||||
image on the page.
|
||||
.PP
|
||||
.IP 5
|
||||
Note: PNG files containing transparency cannot be used when producing
|
||||
Note: Currently PNG support is limited to grayscale, RGB, or indexed files
|
||||
.IP 5
|
||||
PDF/A files. Files containing animation yield the final frame of the
|
||||
without interlacing or alpha. Transparency (masking) based on color/index
|
||||
.IP 5
|
||||
animation. GIF and (optional) WebP support first appeared in PDFio v1.7.
|
||||
.IP 5
|
||||
WebP content is added as a Flate-compressed image with alpha mask as
|
||||
.IP 5
|
||||
needed and is usually significantly larger than the original image.
|
||||
is supported.
|
||||
.SS pdfioFileCreateNameObj
|
||||
Create a new object in a PDF file containing a name.
|
||||
.PP
|
||||
@@ -4287,32 +4090,9 @@ written:
|
||||
.fi
|
||||
|
||||
The "version" argument specifies the PDF version number for the file or
|
||||
\fBNULL\fR for the default ("2.0"). The following values are recognized:
|
||||
.PP
|
||||
.IP \(bu 5
|
||||
"1.3", "1.4", "1.5", "1.6", "1.7", "2.0": Generic PDF files of the
|
||||
specified versions.
|
||||
.IP \(bu 5
|
||||
"PDF/A-1a": PDF/A-1a:2005
|
||||
.IP \(bu 5
|
||||
"PDF/A-1b": PDF/A-1b:2005
|
||||
.IP \(bu 5
|
||||
"PDF/A-2a": PDF/A-2a:2011
|
||||
.IP \(bu 5
|
||||
"PDF/A-2b": PDF/A-2b:2011
|
||||
.IP \(bu 5
|
||||
"PDF/A-2u": PDF/A-2u:2011
|
||||
.IP \(bu 5
|
||||
"PDF/A-3a": PDF/A-3a:2012
|
||||
.IP \(bu 5
|
||||
"PDF/A-3b": PDF/A-3b:2012
|
||||
.IP \(bu 5
|
||||
"PDF/A-3u": PDF/A-3u:2012
|
||||
.IP \(bu 5
|
||||
"PDF/A-4": PDF/A-4:2020
|
||||
.PP
|
||||
Unlike \fIpdfioFileCreate\fR and \fIpdfioFileCreateTemporary\fR, it is
|
||||
generally not safe to pass the "PCLm-1.0" version string.
|
||||
\fBNULL\fR for the default ("2.0"). Unlike \fIpdfioFileCreate\fR and
|
||||
\fIpdfioFileCreateTemporary\fR, it is generally not safe to pass the
|
||||
"PCLm-1.0" version string.
|
||||
.PP
|
||||
The "media_box" and "crop_box" arguments specify the default MediaBox and
|
||||
CropBox for pages in the PDF file - if \fBNULL\fR then a default "Universal" size
|
||||
@@ -4320,24 +4100,9 @@ of 8.27x11in (the intersection of US Letter and ISO A4) is used.
|
||||
.PP
|
||||
The "error_cb" and "error_cbdata" arguments specify an error handler callback
|
||||
and its data pointer - if \fBNULL\fR then the default error handler is used that
|
||||
writes error and warning messages to \fBstderr\fR. The error handler callback
|
||||
should return \fBtrue\fR to continue writing the PDF file or \fBfalse\fR to stop.
|
||||
For example:
|
||||
writes error messages to \fBstderr\fR. The error handler callback should return
|
||||
\fBtrue\fR to continue writing the PDF file or \fBfalse\fR to stop.
|
||||
.PP
|
||||
.nf
|
||||
bool
|
||||
my_error_cb(pdfio_file_t *pdf, const char *message, void *data)
|
||||
{
|
||||
(void)data; /* Not using data pointer in this callback */
|
||||
|
||||
fprintf(stderr, "%s: %sn", pdfioFileGetName(pdf), message);
|
||||
|
||||
/* Return true to continue on warning messages, false otherwise... */
|
||||
return (!strncmp(message, "WARNING:", 8));
|
||||
}
|
||||
|
||||
.fi
|
||||
|
||||
.IP 5
|
||||
\fINote\fR: Files created using this API are slightly larger than those
|
||||
.IP 5
|
||||
@@ -4443,21 +4208,6 @@ const char * pdfioFileGetKeywords (
|
||||
pdfio_file_t *pdf
|
||||
);
|
||||
.fi
|
||||
.SS pdfioFileGetLanguage
|
||||
Get the language metadata for a PDF file.
|
||||
.PP
|
||||
.nf
|
||||
const char * pdfioFileGetLanguage (
|
||||
pdfio_file_t *pdf
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function gets the (primary/default) language metadata, if any, for a PDF
|
||||
file. The returned string is an IETF BCP 47 language tag of the form
|
||||
"lang-REGION". For example, the string "en-CA" specifies Canadian English
|
||||
and the string "fr-CA" specifies Canadian French.
|
||||
|
||||
|
||||
.SS pdfioFileGetModificationDate
|
||||
Get the most recent modification date for a PDF file.
|
||||
.PP
|
||||
@@ -4576,24 +4326,9 @@ PDF file requires a password, the open will always fail.
|
||||
.PP
|
||||
The "error_cb" and "error_cbdata" arguments specify an error handler callback
|
||||
and its data pointer - if \fBNULL\fR then the default error handler is used that
|
||||
writes error and warning messages to \fBstderr\fR. The error handler callback
|
||||
should return \fBtrue\fR to continue reading the PDF file or \fBfalse\fR to stop.
|
||||
For example:
|
||||
writes error messages to \fBstderr\fR. The error handler callback should return
|
||||
\fBtrue\fR to continue reading the PDF file or \fBfalse\fR to stop.
|
||||
.PP
|
||||
.nf
|
||||
bool
|
||||
my_error_cb(pdfio_file_t *pdf, const char *message, void *data)
|
||||
{
|
||||
(void)data; /* Not using data pointer in this callback */
|
||||
|
||||
fprintf(stderr, "%s: %sn", pdfioFileGetName(pdf), message);
|
||||
|
||||
/* Return true to continue on warning messages, false otherwise... */
|
||||
return (!strncmp(message, "WARNING:", 8));
|
||||
}
|
||||
|
||||
.fi
|
||||
|
||||
.IP 5
|
||||
Note: Error messages starting with "WARNING:" are actually warning
|
||||
.IP 5
|
||||
@@ -4638,22 +4373,6 @@ void pdfioFileSetKeywords (
|
||||
const char *value
|
||||
);
|
||||
.fi
|
||||
.SS pdfioFileSetLanguage
|
||||
Set the language metadata for a PDF file.
|
||||
.PP
|
||||
.nf
|
||||
void pdfioFileSetLanguage (
|
||||
pdfio_file_t *pdf,
|
||||
const char *value
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function sets the (primary/default) language metadata for a PDF file.
|
||||
The "value" argument is an IETF BCP 47 language tag string of the form
|
||||
"lang-REGION". For example, the string "en-CA" specifies Canadian English
|
||||
and the string "fr-CA" specifies Canadian French.
|
||||
|
||||
|
||||
.SS pdfioFileSetModificationDate
|
||||
Set the modification date for a PDF file.
|
||||
.PP
|
||||
@@ -4926,91 +4645,6 @@ bool pdfioPageDictAddImage (
|
||||
pdfio_obj_t *obj
|
||||
);
|
||||
.fi
|
||||
.SS pdfioPageGetArray
|
||||
Get an array value from the page dictionary.
|
||||
.PP
|
||||
.nf
|
||||
pdfio_array_t * pdfioPageGetArray (
|
||||
pdfio_obj_t *page,
|
||||
const char *key
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function looks up an array value in the page dictionary, either in the
|
||||
specified object or one of its parents.
|
||||
|
||||
|
||||
.SS pdfioPageGetBinary
|
||||
Get a binary value from the page dictionary.
|
||||
.PP
|
||||
.nf
|
||||
unsigned char * pdfioPageGetBinary (
|
||||
pdfio_obj_t *page,
|
||||
const char *key,
|
||||
size_t *length
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function looks up a binary value in the page dictionary, either in the
|
||||
specified object or one of its parents.
|
||||
|
||||
|
||||
.SS pdfioPageGetBoolean
|
||||
Get a boolean value from the page dictionary.
|
||||
.PP
|
||||
.nf
|
||||
bool pdfioPageGetBoolean (
|
||||
pdfio_obj_t *page,
|
||||
const char *key
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function looks up a boolean value in the page dictionary, either in the
|
||||
specified object or one of its parents.
|
||||
|
||||
|
||||
.SS pdfioPageGetDate
|
||||
Get a date value from the page dictionary.
|
||||
.PP
|
||||
.nf
|
||||
time_t pdfioPageGetDate (
|
||||
pdfio_obj_t *page,
|
||||
const char *key
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function looks up a date value in the page dictionary, either in the
|
||||
specified object or one of its parents.
|
||||
|
||||
|
||||
.SS pdfioPageGetDict
|
||||
Get a dictionary value from the page dictionary.
|
||||
.PP
|
||||
.nf
|
||||
pdfio_dict_t * pdfioPageGetDict (
|
||||
pdfio_obj_t *page,
|
||||
const char *key
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function looks up a dictionary value in the page dictionary, either in
|
||||
the specified object or one of its parents.
|
||||
|
||||
|
||||
.SS pdfioPageGetName
|
||||
Get a name value from the page dictionary.
|
||||
.PP
|
||||
.nf
|
||||
const char * pdfioPageGetName (
|
||||
pdfio_obj_t *page,
|
||||
const char *key
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function looks up a name value in the page dictionary, either in the
|
||||
specified object or one of its parents.
|
||||
|
||||
|
||||
.SS pdfioPageGetNumStreams
|
||||
Get the number of content streams for a page object.
|
||||
.PP
|
||||
@@ -5019,63 +4653,6 @@ size_t pdfioPageGetNumStreams (
|
||||
pdfio_obj_t *page
|
||||
);
|
||||
.fi
|
||||
.SS pdfioPageGetNumber
|
||||
Get a number value from the page dictionary.
|
||||
.PP
|
||||
.nf
|
||||
double pdfioPageGetNumber (
|
||||
pdfio_obj_t *page,
|
||||
const char *key
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function looks up a number value in the page dictionary, either in the
|
||||
specified object or one of its parents.
|
||||
|
||||
|
||||
.SS pdfioPageGetObj
|
||||
Get an indirect object value from the page dictionary.
|
||||
.PP
|
||||
.nf
|
||||
pdfio_obj_t * pdfioPageGetObj (
|
||||
pdfio_obj_t *page,
|
||||
const char *key
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function looks up an indirect object value in the page dictionary,
|
||||
either in the specified object or one of its parents.
|
||||
|
||||
|
||||
.SS pdfioPageGetRect
|
||||
Get a rectangle value from the page dictionary.
|
||||
.PP
|
||||
.nf
|
||||
pdfio_rect_t * pdfioPageGetRect (
|
||||
pdfio_obj_t *page,
|
||||
const char *key,
|
||||
pdfio_rect_t *rect
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function looks up a rectangle value in the page dictionary, either in
|
||||
the specified object or one of its parents.
|
||||
|
||||
|
||||
.SS pdfioPageGetString
|
||||
Get a string value from the page dictionary.
|
||||
.PP
|
||||
.nf
|
||||
const char * pdfioPageGetString (
|
||||
pdfio_obj_t *page,
|
||||
const char *key
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function looks up a string value in the page dictionary, either in the
|
||||
specified object or one of its parents.
|
||||
|
||||
|
||||
.SS pdfioPageOpenStream
|
||||
Open a content stream for a page.
|
||||
.PP
|
||||
@@ -5353,4 +4930,4 @@ typedef enum pdfio_valtype_e pdfio_valtype_t;
|
||||
Michael R Sweet
|
||||
.SH COPYRIGHT
|
||||
.PP
|
||||
Copyright (c) 2021-2026 by Michael R Sweet
|
||||
Copyright (c) 2021-2025 by Michael R Sweet
|
||||
|
||||
697
doc/pdfio.html
174
doc/pdfio.md
@@ -15,9 +15,9 @@ goals of PDFio are:
|
||||
PDFio is *not* concerned with rendering or viewing a PDF file, although a PDF
|
||||
RIP or viewer could be written using it.
|
||||
|
||||
Copyright © 2021-2026 by Michael R Sweet. PDFio is licensed under the Apache
|
||||
License Version 2.0 with an (optional) exception to allow linking against GNU
|
||||
GPL2-only software. See the files `LICENSE` and `NOTICE` for more information.
|
||||
PDFio is Copyright © 2021-2025 by Michael R Sweet and is licensed under the
|
||||
Apache License Version 2.0 with an (optional) exception to allow linking against
|
||||
GPL2/LGPL2 software. See the files "LICENSE" and "NOTICE" for more information.
|
||||
|
||||
|
||||
Requirements
|
||||
@@ -28,22 +28,16 @@ PDFio requires the following to build the software:
|
||||
- A C99 compiler such as Clang, GCC, or MS Visual C
|
||||
- A POSIX-compliant `make` program
|
||||
- A POSIX-compliant `sh` program
|
||||
- libpng (<https://www.libpng.org/>) 1.6 or later for full PNG image support
|
||||
(optional)
|
||||
- libwebp (<https://developers.google.com/speed/webp>) 1.0 or later for WebP
|
||||
image support (optional)
|
||||
- ZLIB (<https://www.zlib.net/>) 1.1 or later for compression support
|
||||
- ZLIB (<https://www.zlib.net/>) 1.0 or higher
|
||||
|
||||
PDFio will also use libpng 1.6 or higher (<https://www.libpng.org/>) to provide
|
||||
enhanced PNG image support.
|
||||
|
||||
IDE files for Xcode (macOS/iOS) and Visual Studio (Windows) are also provided.
|
||||
|
||||
On a stock Ubuntu install, the following command will install the various
|
||||
prerequisites:
|
||||
|
||||
sudo apt-get install build-essential libpng-dev libwebp-dev zlib1g-dev
|
||||
|
||||
|
||||
Building and Installing PDFio on Linux/Unix
|
||||
-------------------------------------------
|
||||
Installing PDFio
|
||||
----------------
|
||||
|
||||
PDFio comes with a configure script that creates a portable makefile that will
|
||||
work on any POSIX-compliant system with ZLIB installed. To make it, run:
|
||||
@@ -75,32 +69,21 @@ Other configure options can be found using the `--help` option:
|
||||
./configure --help
|
||||
|
||||
|
||||
Building on Windows with Visual Studio
|
||||
--------------------------------------
|
||||
Visual Studio Project
|
||||
---------------------
|
||||
|
||||
The Visual Studio solution ("pdfio.sln") is provided for Windows developers and
|
||||
generates the PDFIO1 DLL. You can also use NuGet to install the `pdfio_native`
|
||||
package.
|
||||
|
||||
You can build and run the `testpdfio` unit tests target from within Visual
|
||||
Studio to verify the functioning of the library.
|
||||
generates both a static library and DLL.
|
||||
|
||||
|
||||
Building on macOS with Xcode
|
||||
----------------------------
|
||||
Xcode Project
|
||||
-------------
|
||||
|
||||
The Xcode project (`pdfio.xcodeproj`) is provided for macOS developer which
|
||||
generates a static library that will be installed under "/usr/local". Run the
|
||||
following command to build and install PDFio on macOS:
|
||||
There is also an Xcode project ("pdfio.xcodeproj") you can use on macOS which
|
||||
generates a static library that will be installed under "/usr/local" with:
|
||||
|
||||
sudo xcodebuild install
|
||||
|
||||
Alternately you can add the Xcode project to a workspace and reference the PDFio
|
||||
library target as a dependency in your own project.
|
||||
|
||||
You can build and run the `testpdfio` unit tests target from within Xcode to
|
||||
verify the functioning of the library.
|
||||
|
||||
|
||||
Detecting PDFio
|
||||
---------------
|
||||
@@ -404,35 +387,43 @@ Each page is represented by a "page tree" object (what [`pdfioFileGetPage`](@@)
|
||||
returns) that specifies information about the page and one or more "content"
|
||||
objects that contain the images, fonts, text, and graphics that appear on the
|
||||
page. Use the [`pdfioPageGetNumStreams`](@@) and [`pdfioPageOpenStream`](@@)
|
||||
functions to access the content streams for each page, [`pdfioObjGetDict`](@@)
|
||||
to get the associated page object dictionary, and [`pdfioPageGetArray`](@@),
|
||||
[`pdfioPageGetBinary`](@@), [`pdfioPageGetBoolean`](@@),
|
||||
[`pdfioPageGetDate`](@@), [`pdfioPageGetDict`](@@), [`pdfioPageGetName`](@@),
|
||||
[`pdfioPageGetObj`](@@), [`pdfioPageGetRect`](@@), and
|
||||
[`pdfioPageGetString`](@@) to get a value from the page object dictionary or its
|
||||
parents. For example, if you want to display the media and crop boxes for a
|
||||
given page:
|
||||
functions to access the content streams for each page, and
|
||||
[`pdfioObjGetDict`](@@) to get the associated page object dictionary. For
|
||||
example, if you want to display the media and crop boxes for a given page:
|
||||
|
||||
```c
|
||||
pdfio_file_t *pdf; // PDF file
|
||||
size_t i; // Looping var
|
||||
size_t count; // Number of pages
|
||||
pdfio_obj_t *page; // Current page
|
||||
pdfio_rect_t media_box; // MediaBox values
|
||||
pdfio_rect_t crop_box; // CropBox values
|
||||
pdfio_dict_t *dict; // Current page dictionary
|
||||
pdfio_array_t *media_box; // MediaBox array
|
||||
double media_values[4]; // MediaBox values
|
||||
pdfio_array_t *crop_box; // CropBox array
|
||||
double crop_values[4]; // CropBox values
|
||||
|
||||
// Iterate the pages in the PDF file
|
||||
for (i = 0, count = pdfioFileGetNumPages(pdf); i < count; i ++)
|
||||
{
|
||||
page = pdfioFileGetPage(pdf, i);
|
||||
dict = pdfioObjGetDict(page);
|
||||
|
||||
pdfioPageGetRect(page, "MediaBox", &media_box);
|
||||
pdfioPageGetRect(page, "CropBox", &crop_box);
|
||||
media_box = pdfioDictGetArray(dict, "MediaBox");
|
||||
media_values[0] = pdfioArrayGetNumber(media_box, 0);
|
||||
media_values[1] = pdfioArrayGetNumber(media_box, 1);
|
||||
media_values[2] = pdfioArrayGetNumber(media_box, 2);
|
||||
media_values[3] = pdfioArrayGetNumber(media_box, 3);
|
||||
|
||||
crop_box = pdfioDictGetArray(dict, "CropBox");
|
||||
crop_values[0] = pdfioArrayGetNumber(crop_box, 0);
|
||||
crop_values[1] = pdfioArrayGetNumber(crop_box, 1);
|
||||
crop_values[2] = pdfioArrayGetNumber(crop_box, 2);
|
||||
crop_values[3] = pdfioArrayGetNumber(crop_box, 3);
|
||||
|
||||
printf("Page %u: MediaBox=[%g %g %g %g], CropBox=[%g %g %g %g]\n",
|
||||
(unsigned)(i + 1),
|
||||
media_box.x1, media_box.y1, media_box.x2, media_box.y2,
|
||||
crop_box.x1, crop_box.y1, crop_box.x2, crop_box.y2);
|
||||
media_values[0], media_values[1], media_values[2], media_values[3],
|
||||
crop_values[0], crop_values[1], crop_values[2], crop_values[3]);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -769,9 +760,8 @@ The "interpolate" argument specifies whether the colors in the image should be
|
||||
smoothed/interpolated when scaling. This is most useful for photographs but
|
||||
should be `false` for screenshot and barcode images.
|
||||
|
||||
If you have a GIF, JPEG, PNG, or WebP file, use the
|
||||
[`pdfioFileCreateImageObjFromFile`](@@) function to copy the image into a PDF
|
||||
image object, for example:
|
||||
If you have a JPEG or PNG file, use the [`pdfioFileCreateImageObjFromFile`](@@)
|
||||
function to copy the image into a PDF image object, for example:
|
||||
|
||||
```c
|
||||
pdfio_file_t *pdf = pdfioFileCreate(...);
|
||||
@@ -779,6 +769,9 @@ pdfio_obj_t *img =
|
||||
pdfioFileCreateImageObjFromFile(pdf, "myphoto.jpg", /*interpolate*/true);
|
||||
```
|
||||
|
||||
> Note: Currently `pdfioFileCreateImageObjFromFile` does not support 12 bit JPEG
|
||||
> files or PNG files with an alpha channel.
|
||||
|
||||
|
||||
### Page Dictionary Functions
|
||||
|
||||
@@ -875,55 +868,6 @@ escaping, as needed:
|
||||
offsets between them
|
||||
|
||||
|
||||
Tagged and Marked PDF Content
|
||||
-----------------------------
|
||||
|
||||
Content in a page stream can be tagged to help a PDF reader application know the
|
||||
kind and organization of that content. Content inserted using the PDFio
|
||||
[Page Stream Functions](@) can be tagged by surrounding it with the
|
||||
[`pdfioContentBeginMarked`](@@) and [`pdfioContentEndMarked`](@@) functions.
|
||||
|
||||
The `pdfioContentBeginMarked` function accepts a named tag and optional
|
||||
dictionary of attributes such as the marked content identifier ("MCID"). For
|
||||
example, the following code tags a paragraph of text:
|
||||
|
||||
```c
|
||||
pdfio_file_t *pdf; // PDF file
|
||||
pdfio_stream_t *st; // Page stream
|
||||
|
||||
pdfioContentBeginMarked(st, "P", /*dict*/NULL);
|
||||
|
||||
pdfioContentTextShow(st, /*unicode*/false, "Mary had a little lamb\n");
|
||||
pdfioContentTextShow(st, /*unicode*/false, "whose fleece was white as snow.\n");
|
||||
pdfioContentTextShow(st, /*unicode*/false, "And everywhere that Mary went\n");
|
||||
pdfioContentTextShow(st, /*unicode*/false, "the lamb was sure to go,\n");
|
||||
|
||||
pdfioContentEndMarked(st);
|
||||
```
|
||||
|
||||
To mark the same paragraph with a content identifier you would first create a
|
||||
dictionary containing the "MCID" key/value pair and then mark the paragraph with
|
||||
that dictionary:
|
||||
|
||||
```c
|
||||
pdfio_file_t *pdf; // PDF file
|
||||
pdfio_stream_t *st; // Page stream
|
||||
pdfio_dict_t *dict; // Content dictionary
|
||||
|
||||
dict = pdfioDictCreate(pdf);
|
||||
pdfioDictSetNumber(dict, "MCID", 42);
|
||||
|
||||
pdfioContentBeginMarked(st, "P", dict);
|
||||
|
||||
pdfioContentTextShow(st, /*unicode*/false, "Mary had a little lamb\n");
|
||||
pdfioContentTextShow(st, /*unicode*/false, "whose fleece was white as snow.\n");
|
||||
pdfioContentTextShow(st, /*unicode*/false, "And everywhere that Mary went\n");
|
||||
pdfioContentTextShow(st, /*unicode*/false, "the lamb was sure to go,\n");
|
||||
|
||||
pdfioContentEndMarked(st);
|
||||
```
|
||||
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
@@ -1036,10 +980,16 @@ main(int argc, // I - Number of command-line arguments
|
||||
for (cur = 0, prev = 0; cur < num_pages; cur ++)
|
||||
{
|
||||
// Find the MediaBox for this page in the page tree...
|
||||
page = pdfioFileGetPage(pdf, cur);
|
||||
for (page = pdfioFileGetPage(pdf, cur);
|
||||
page != NULL;
|
||||
page = pdfioDictGetObj(page_dict, "Parent"))
|
||||
{
|
||||
cur_box.x1 = cur_box.x2 = cur_box.y1 = cur_box.y2 = 0.0;
|
||||
page_dict = pdfioObjGetDict(page);
|
||||
|
||||
cur_box.x1 = cur_box.x2 = cur_box.y1 = cur_box.y2 = 0.0;
|
||||
pdfioPageGetRect(page, "MediaBox", &cur_box);
|
||||
if (pdfioDictGetRect(page_dict, "MediaBox", &cur_box))
|
||||
break;
|
||||
}
|
||||
|
||||
// If this MediaBox is different from the previous one, show the range of
|
||||
// pages that have that size...
|
||||
@@ -1343,7 +1293,7 @@ Unicode glyph for the current index:
|
||||
Create a PDF File With Text and an Image
|
||||
----------------------------------------
|
||||
|
||||
The `image2pdf.c` example code creates a PDF file containing a GIF, JPEG, or PNG
|
||||
The `image2pdf.c` example code creates a PDF file containing a JPEG or PNG
|
||||
image file and optional caption on a single page. The `create_pdf_image_file`
|
||||
function creates the PDF file, embeds a base font and the named JPEG or PNG
|
||||
image file, and then creates a page with the image centered on the page with any
|
||||
@@ -1647,9 +1597,6 @@ typedef struct docdata_s // Document formatting data
|
||||
// State for the current page
|
||||
pdfio_stream_t *st; // Current page stream
|
||||
double y; // Current position on page
|
||||
const char *tag; // Current block tag
|
||||
bool in_table, // Are we in a table?
|
||||
in_row; // Are we in a table row?
|
||||
docfont_t font; // Current font
|
||||
double fsize; // Current font size
|
||||
doccolor_t color; // Current color
|
||||
@@ -2153,9 +2100,6 @@ pdfioContentPathRect(dd->st, left - CODE_PADDING, dd->y + SIZE_CODEBLOCK,
|
||||
pdfioContentFillAndStroke(dd->st, false);
|
||||
|
||||
// Start a code text block...
|
||||
dd->tag = "P";
|
||||
pdfioContentBeginMarked(dd->st, dd->tag, /*dict*/NULL);
|
||||
|
||||
set_font(dd, DOCFONT_MONOSPACE, SIZE_CODEBLOCK);
|
||||
pdfioContentTextBegin(dd->st);
|
||||
pdfioContentTextMoveTo(dd->st, left, dd->y);
|
||||
@@ -2192,9 +2136,6 @@ for (code = mmdGetFirstChild(block); code; code = mmdGetNextSibling(code))
|
||||
pdfioContentTextEnd(dd->st);
|
||||
dd->y += lineheight;
|
||||
|
||||
pdfioContentEndMarked(dd->st);
|
||||
dd->tag = NULL;
|
||||
|
||||
// Draw the bottom padding...
|
||||
set_color(dd, DOCCOLOR_LTGRAY);
|
||||
pdfioContentPathRect(dd->st, left - CODE_PADDING,
|
||||
@@ -2335,17 +2276,8 @@ Finally, we render each row in the table:
|
||||
|
||||
```c
|
||||
// Render each table row...
|
||||
dd->in_table = true;
|
||||
|
||||
if (dd->st)
|
||||
pdfioContentBeginMarked(dd->st, "Table", /*dict*/NULL);
|
||||
|
||||
for (row = 0, rowptr = rows; row < num_rows; row ++, rowptr ++)
|
||||
render_row(dd, num_cols, cols, rowptr);
|
||||
|
||||
pdfioContentEndMarked(dd->st);
|
||||
|
||||
dd->in_table = false;
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
|
||||
#include <pdfio.h>
|
||||
#include <pdfio-content.h>
|
||||
#ifdef _WIN32
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// Simple markdown to PDF converter example for PDFio.
|
||||
//
|
||||
// Copyright © 2024-2025 by Michael R Sweet.
|
||||
// Copyright © 2024 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <math.h>
|
||||
#ifdef _WIN32
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif // _WIN32
|
||||
@@ -123,9 +122,6 @@ typedef struct docdata_s // Document formatting data
|
||||
// State for the current page
|
||||
pdfio_stream_t *st; // Current page stream
|
||||
double y; // Current position on page
|
||||
const char *tag; // Current block tag
|
||||
bool in_table, // Are we in a table?
|
||||
in_row; // Are we in a table row?
|
||||
docfont_t font; // Current font
|
||||
double fsize; // Current font size
|
||||
doccolor_t color; // Current color
|
||||
@@ -293,8 +289,8 @@ main(int argc, // I - Number of command-line arguments
|
||||
// Get the markdown file from the command-line...
|
||||
if (argc < 2 || argc > 3)
|
||||
{
|
||||
fputs("Usage: md2pdf FILENAME.md [FILENAME.pdf]\n", stderr);
|
||||
fputs(" md2pdf FILENAME.md >FILENAME.pdf\n", stderr);
|
||||
fputs("Usage: md2pdf FILENANE.md [FILENAME.pdf]\n", stderr);
|
||||
fputs(" md2pdf FILENANE.md >FILENAME.pdf\n", stderr);
|
||||
return (1);
|
||||
}
|
||||
|
||||
@@ -476,7 +472,6 @@ add_links(docdata_t *dd) // I - Document data
|
||||
// Create the annotation object pointing to the action...
|
||||
dict = pdfioDictCreate(dd->pdf);
|
||||
pdfioDictSetName(dict, "Subtype", "Link");
|
||||
pdfioDictSetNumber(dict, "F", 4); // Print flag
|
||||
pdfioDictSetRect(dict, "Rect", &l->box);
|
||||
border = pdfioArrayCreate(dd->pdf);
|
||||
pdfioArrayAppendNumber(border, 0.0);
|
||||
@@ -623,50 +618,6 @@ format_block(docdata_t *dd, // I - Document data
|
||||
|
||||
frag = frags + num_frags;
|
||||
|
||||
switch (mmdGetType(block))
|
||||
{
|
||||
case MMD_TYPE_HEADING_1 :
|
||||
dd->tag = "H1";
|
||||
break;
|
||||
|
||||
case MMD_TYPE_HEADING_2 :
|
||||
dd->tag = "H2";
|
||||
break;
|
||||
|
||||
case MMD_TYPE_HEADING_3 :
|
||||
dd->tag = "H3";
|
||||
break;
|
||||
|
||||
case MMD_TYPE_HEADING_4 :
|
||||
dd->tag = "H4";
|
||||
break;
|
||||
|
||||
case MMD_TYPE_HEADING_5 :
|
||||
dd->tag = "H5";
|
||||
break;
|
||||
|
||||
case MMD_TYPE_HEADING_6 :
|
||||
dd->tag = "H6";
|
||||
break;
|
||||
|
||||
case MMD_TYPE_TABLE_HEADER_CELL :
|
||||
dd->tag = "TH";
|
||||
break;
|
||||
|
||||
case MMD_TYPE_TABLE_BODY_CELL_LEFT :
|
||||
case MMD_TYPE_TABLE_BODY_CELL_CENTER :
|
||||
case MMD_TYPE_TABLE_BODY_CELL_RIGHT :
|
||||
dd->tag = "TD";
|
||||
break;
|
||||
|
||||
default :
|
||||
dd->tag = "P";
|
||||
break;
|
||||
}
|
||||
|
||||
if (dd->st)
|
||||
pdfioContentBeginMarked(dd->st, dd->tag, /*dict*/NULL);
|
||||
|
||||
// Loop through the block and render lines...
|
||||
for (current = mmdGetFirstChild(block), x = left; current; current = next)
|
||||
{
|
||||
@@ -845,9 +796,6 @@ format_block(docdata_t *dd, // I - Document data
|
||||
pdfioContentRestore(dd->st);
|
||||
}
|
||||
}
|
||||
|
||||
pdfioContentEndMarked(dd->st);
|
||||
dd->tag = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -887,9 +835,6 @@ format_code(docdata_t *dd, // I - Document data
|
||||
pdfioContentFillAndStroke(dd->st, false);
|
||||
|
||||
// Start a code text block...
|
||||
dd->tag = "P";
|
||||
pdfioContentBeginMarked(dd->st, dd->tag, /*dict*/NULL);
|
||||
|
||||
set_font(dd, DOCFONT_MONOSPACE, SIZE_CODEBLOCK);
|
||||
pdfioContentTextBegin(dd->st);
|
||||
pdfioContentTextMoveTo(dd->st, left, dd->y);
|
||||
@@ -924,9 +869,6 @@ format_code(docdata_t *dd, // I - Document data
|
||||
pdfioContentTextEnd(dd->st);
|
||||
dd->y += lineheight;
|
||||
|
||||
pdfioContentEndMarked(dd->st);
|
||||
dd->tag = NULL;
|
||||
|
||||
// Draw the bottom padding...
|
||||
set_color(dd, DOCCOLOR_LTGRAY);
|
||||
pdfioContentPathRect(dd->st, left - CODE_PADDING, dd->y - CODE_PADDING - (LINE_HEIGHT - 1.0) * SIZE_CODEBLOCK, right - left + 2.0 * CODE_PADDING, CODE_PADDING);
|
||||
@@ -1202,17 +1144,8 @@ format_table(docdata_t *dd, // I - Document data
|
||||
}
|
||||
|
||||
// Render each table row...
|
||||
dd->in_table = true;
|
||||
|
||||
if (dd->st)
|
||||
pdfioContentBeginMarked(dd->st, "Table", /*dict*/NULL);
|
||||
|
||||
for (row = 0, rowptr = rows; row < num_rows; row ++, rowptr ++)
|
||||
render_row(dd, num_cols, cols, rowptr);
|
||||
|
||||
pdfioContentEndMarked(dd->st);
|
||||
|
||||
dd->in_table = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1426,16 +1359,6 @@ new_page(docdata_t *dd) // I - Document data
|
||||
// Close the current page...
|
||||
if (dd->st)
|
||||
{
|
||||
if (dd->tag)
|
||||
{
|
||||
// Close current tag and any row or table...
|
||||
pdfioContentEndMarked(dd->st);
|
||||
if (dd->in_row)
|
||||
pdfioContentEndMarked(dd->st);
|
||||
if (dd->in_table)
|
||||
pdfioContentEndMarked(dd->st);
|
||||
}
|
||||
|
||||
pdfioStreamClose(dd->st);
|
||||
add_links(dd);
|
||||
}
|
||||
@@ -1464,7 +1387,6 @@ new_page(docdata_t *dd) // I - Document data
|
||||
dd->y = dd->art_box.y2;
|
||||
|
||||
// Add header/footer text
|
||||
pdfioContentBeginMarked(dd->st, "Artifact", /*dict*/NULL);
|
||||
set_color(dd, DOCCOLOR_GRAY);
|
||||
set_font(dd, DOCFONT_REGULAR, SIZE_HEADFOOT);
|
||||
|
||||
@@ -1523,17 +1445,6 @@ new_page(docdata_t *dd) // I - Document data
|
||||
pdfioContentTextShow(dd->st, UNICODE_VALUE, dd->heading);
|
||||
pdfioContentTextEnd(dd->st);
|
||||
}
|
||||
|
||||
pdfioContentEndMarked(dd->st);
|
||||
|
||||
if (dd->in_table)
|
||||
pdfioContentBeginMarked(dd->st, "Table", /*dict*/NULL);
|
||||
|
||||
if (dd->in_row)
|
||||
pdfioContentBeginMarked(dd->st, "TR", /*dict*/NULL);
|
||||
|
||||
if (dd->tag)
|
||||
pdfioContentBeginMarked(dd->st, dd->tag, /*dict*/NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -1706,11 +1617,9 @@ render_row(docdata_t *dd, // I - Document data
|
||||
// Start a new page as needed...
|
||||
if (!dd->st)
|
||||
new_page(dd);
|
||||
else if ((dd->y - row->height) < dd->art_box.y1)
|
||||
new_page(dd);
|
||||
|
||||
dd->in_row = true;
|
||||
pdfioContentBeginMarked(dd->st, "TR", /*dict*/NULL);
|
||||
if ((dd->y - row->height) < dd->art_box.y1)
|
||||
new_page(dd);
|
||||
|
||||
if (mmdGetType(row->cells[0]) == MMD_TYPE_TABLE_HEADER_CELL)
|
||||
{
|
||||
@@ -1742,9 +1651,6 @@ render_row(docdata_t *dd, // I - Document data
|
||||
}
|
||||
|
||||
dd->y = row_y - row->height;
|
||||
|
||||
pdfioContentEndMarked(dd->st);
|
||||
dd->in_row = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// https://www.msweet.org/mmd
|
||||
//
|
||||
// Copyright © 2017-2025 by Michael R Sweet.
|
||||
// Copyright © 2017-2024 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -166,7 +166,7 @@ mmdCopyAllText(mmd_t *node) // I - Parent node
|
||||
char *all = NULL, // String buffer
|
||||
*allptr = NULL, // Pointer into string buffer
|
||||
*temp; // Temporary pointer
|
||||
size_t allsize = 0, // Size of "all" buffer
|
||||
size_t allsize = 1, // Size of "all" buffer
|
||||
textlen; // Length of "text" string
|
||||
mmd_t *current, // Current node
|
||||
*next; // Next node
|
||||
@@ -179,8 +179,6 @@ mmdCopyAllText(mmd_t *node) // I - Parent node
|
||||
if (current->text)
|
||||
{
|
||||
// Append this node's text to the string...
|
||||
long alloff = allptr - all; // Offset within current buffer
|
||||
|
||||
textlen = strlen(current->text);
|
||||
allsize += textlen + (size_t)current->whitespace;
|
||||
temp = realloc(all, allsize);
|
||||
@@ -191,8 +189,8 @@ mmdCopyAllText(mmd_t *node) // I - Parent node
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
allptr = temp + (allptr - all);
|
||||
all = temp;
|
||||
allptr = all + alloff;
|
||||
|
||||
if (current->whitespace)
|
||||
*allptr++ = ' ';
|
||||
@@ -1061,8 +1059,6 @@ mmdLoadIO(mmd_t *root, // I - Root node for document or `NULL` for a new d
|
||||
break;
|
||||
else if (line[0] == '>' && *ptr == '>')
|
||||
memmove(ptr, ptr + 1, strlen(ptr));
|
||||
|
||||
DEBUG2_printf(" line=\"%s\"\n", line);
|
||||
}
|
||||
|
||||
mmd_parse_inline(&doc, block, lineptr);
|
||||
@@ -1497,7 +1493,7 @@ mmd_parse_inline(_mmd_doc_t *doc, // I - Document
|
||||
|
||||
for (text = NULL, type = MMD_TYPE_NORMAL_TEXT; *lineptr; lineptr ++)
|
||||
{
|
||||
DEBUG2_printf("mmd_parse_inline: lineptr=%p(\"%s\"), type=%d, text=%p, whitespace=%d\n", lineptr, lineptr, type, text, whitespace);
|
||||
DEBUG2_printf("mmd_parse_inline: lineptr=%p(\"%32.32s...\"), type=%d, text=%p, whitespace=%d\n", lineptr, lineptr, type, text, whitespace);
|
||||
|
||||
if (isspace(*lineptr & 255) && type != MMD_TYPE_CODE_TEXT)
|
||||
{
|
||||
@@ -2094,8 +2090,6 @@ mmd_read_buffer(_mmd_filebuf_t *file) // I - File buffer
|
||||
if (file->bufptr && file->bufptr > file->buffer)
|
||||
{
|
||||
// Discard previous characters in the buffer.
|
||||
DEBUG2_printf("mmd_read_buffer: before buffer=\"%s\"\n", file->bufptr);
|
||||
|
||||
memmove(file->buffer, file->bufptr, file->bufend - file->bufptr);
|
||||
file->bufend -= (file->bufptr - file->buffer);
|
||||
}
|
||||
@@ -2105,13 +2099,11 @@ mmd_read_buffer(_mmd_filebuf_t *file) // I - File buffer
|
||||
file->bufend = file->buffer;
|
||||
}
|
||||
|
||||
if ((bytes = (file->cb)(file->cbdata, file->bufend, sizeof(file->buffer) - (size_t)(file->bufend - file->buffer) - 1)) > 0)
|
||||
if ((bytes = (file->cb)(file->cbdata, file->bufend, sizeof(file->buffer) - (size_t)(file->bufend - file->buffer - 1))) > 0)
|
||||
file->bufend += bytes;
|
||||
|
||||
*(file->bufend) = '\0';
|
||||
file->bufptr = file->buffer;
|
||||
|
||||
DEBUG2_printf("mmd_read_buffer: after buffer=\"%s\"\n", file->buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -2169,8 +2161,6 @@ mmd_read_line(_mmd_filebuf_t *file, // I - File buffer
|
||||
else if (!strchr(file->bufptr, '\n'))
|
||||
mmd_read_buffer(file);
|
||||
|
||||
DEBUG2_printf("mmd_read_line: Returning \"%s\"\n", line);
|
||||
|
||||
return (line);
|
||||
}
|
||||
|
||||
|
||||
@@ -1417,4 +1417,4 @@ puts_utf16(const char *s) // I - Hex string
|
||||
|
||||
put_utf8(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// PDF metadata example for PDFio.
|
||||
//
|
||||
// Copyright © 2023-2026 by Michael R Sweet.
|
||||
// Copyright © 2023-2025 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -113,10 +113,16 @@ main(int argc, // I - Number of command-line arguments
|
||||
for (cur = 0, prev = 0; cur < num_pages; cur ++)
|
||||
{
|
||||
// Find the MediaBox for this page in the page tree...
|
||||
page = pdfioFileGetPage(pdf, cur);
|
||||
for (page = pdfioFileGetPage(pdf, cur);
|
||||
page != NULL;
|
||||
page = pdfioDictGetObj(page_dict, "Parent"))
|
||||
{
|
||||
cur_box.x1 = cur_box.x2 = cur_box.y1 = cur_box.y2 = 0.0;
|
||||
page_dict = pdfioObjGetDict(page);
|
||||
|
||||
cur_box.x1 = cur_box.x2 = cur_box.y1 = cur_box.y2 = 0.0;
|
||||
pdfioPageGetRect(page, "MediaBox", &cur_box);
|
||||
if (pdfioDictGetRect(page_dict, "MediaBox", &cur_box))
|
||||
break;
|
||||
}
|
||||
|
||||
// If this MediaBox is different from the previous one, show the range of
|
||||
// pages that have that size...
|
||||
|
||||
41
makesrcdist
@@ -7,10 +7,6 @@
|
||||
# ./makesrcdist [--snapshot] VERSION
|
||||
#
|
||||
|
||||
# Save the current directory...
|
||||
basedir="$(pwd)"
|
||||
|
||||
|
||||
# Support "--snapshot" option...
|
||||
if test "$1" == "--snapshot"; then
|
||||
shift
|
||||
@@ -19,21 +15,18 @@ else
|
||||
snapshot=0
|
||||
fi
|
||||
|
||||
|
||||
# Get the release version...
|
||||
# Get version...
|
||||
if test $# != 1; then
|
||||
echo "Usage: ./makesrcdist [--snapshot] VERSION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
status=0
|
||||
version=$1
|
||||
version_major=$(echo $1 | awk -F. '{print $1}')
|
||||
version_minor=$(echo $1 | awk -F. '{print $2}')
|
||||
|
||||
|
||||
# Check that version number has been updated everywhere...
|
||||
status=0
|
||||
|
||||
if test $(grep AC_INIT configure.ac | awk '{print $2}') != "[$version],"; then
|
||||
echo "Still need to update AC_INIT version in 'configure.ac'."
|
||||
status=1
|
||||
@@ -85,32 +78,18 @@ if test $status = 1; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Tag release...
|
||||
if test $snapshot = 0; then
|
||||
echo "Creating tag v$version for release..."
|
||||
echo Creating tag for release...
|
||||
git tag -m "Tag $version" v$version
|
||||
git push origin v$version
|
||||
fi
|
||||
|
||||
# Make source archives...
|
||||
echo Creating pdfio-$version.tar.gz...
|
||||
git archive --format tar --prefix=pdfio-$version/ HEAD | gzip -v9 >pdfio-$version.tar.gz
|
||||
gpg --detach-sign pdfio-$version.tar.gz
|
||||
|
||||
# Make and sign source archives...
|
||||
echo "Exporting $version..."
|
||||
rm -rf $TMPDIR/pdfio-$version
|
||||
mkdir $TMPDIR/pdfio-$version
|
||||
git archive --format tar HEAD | (cd $TMPDIR/pdfio-$version; tar xf -)
|
||||
(cd ttf; git archive --prefix=ttf/ HEAD) | (cd $TMPDIR/pdfio-$version; tar xf -)
|
||||
cd $TMPDIR
|
||||
|
||||
echo "Creating pdfio-$version.tar.gz..."
|
||||
tar cf - pdfio-$version | gzip -v9 >"$basedir/pdfio-$version.tar.gz"
|
||||
gpg --detach-sign "$basedir/pdfio-$version.tar.gz"
|
||||
|
||||
echo "Creating pdfio-$version.zip..."
|
||||
zip -r "$basedir/pdfio-$version.zip" pdfio-$version
|
||||
gpg --detach-sign "$basedir/pdfio-$version.zip"
|
||||
|
||||
|
||||
# Clean up...
|
||||
echo "Removing temporary files..."
|
||||
rm -rf pdfio-$version
|
||||
echo Creating pdfio-$version.zip...
|
||||
git archive --format zip --prefix=pdfio-$version/ HEAD >pdfio-$version.zip
|
||||
gpg --detach-sign pdfio-$version.zip
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// AES functions for PDFio.
|
||||
//
|
||||
// Copyright © 2021-2026 by Michael R Sweet.
|
||||
// Copyright © 2021-2025 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -117,7 +117,7 @@ _pdfioCryptoAESInit(
|
||||
memcpy(ctx->round_key, key, keylen);
|
||||
|
||||
// All other round keys are found from the previous round keys.
|
||||
for (rkptr0 = ctx->round_key, rkptr = rkptr0 + keylen, rkend = rkptr0 + 16 * ctx->round_size + 16, i = nwords; rkptr < rkend; i ++)
|
||||
for (rkptr0 = ctx->round_key, rkptr = rkptr0 + keylen, rkend = rkptr + 16 * ctx->round_size, i = nwords; rkptr < rkend; i ++)
|
||||
{
|
||||
if ((i % nwords) == 0)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// PDF array functions for PDFio.
|
||||
//
|
||||
// Copyright © 2021-2026 by Michael R Sweet.
|
||||
// Copyright © 2021-2024 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -262,11 +262,7 @@ pdfioArrayCopy(pdfio_file_t *pdf, // I - PDF file
|
||||
vdst; // Current destination value
|
||||
|
||||
|
||||
PDFIO_DEBUG("pdfioArrayCopy(pdf=%p, a=%p(%p))\n", (void *)pdf, (void *)a, a ? (void *)a->pdf : NULL);
|
||||
|
||||
// Range check input...
|
||||
if (!pdf || !a)
|
||||
return (NULL);
|
||||
PDFIO_DEBUG("pdfioArrayCopy(pdf=%p, a=%p(%p))\n", pdf, a, a ? a->pdf : NULL);
|
||||
|
||||
// Create the new array...
|
||||
if ((na = pdfioArrayCreate(pdf)) == NULL)
|
||||
@@ -610,7 +606,7 @@ _pdfioArrayRead(pdfio_file_t *pdf, // I - PDF file
|
||||
_pdfio_value_t value; // Value
|
||||
|
||||
|
||||
PDFIO_DEBUG("_pdfioArrayRead(pdf=%p, tb=%p)\n", (void *)pdf, (void *)tb);
|
||||
PDFIO_DEBUG("_pdfioArrayRead(pdf=%p, tb=%p)\n", pdf, tb);
|
||||
|
||||
// Create an array...
|
||||
if ((array = pdfioArrayCreate(pdf)) == NULL)
|
||||
@@ -670,29 +666,27 @@ pdfioArrayRemove(pdfio_array_t *a, // I - Array
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` otherwise
|
||||
_pdfioArrayWrite(
|
||||
_pdfio_printf_t cb, // I - Printf callback function
|
||||
void *cbdata, // I - Printf callback data
|
||||
pdfio_obj_t *obj, // I - Object, if any
|
||||
pdfio_array_t *a) // I - Array
|
||||
_pdfioArrayWrite(pdfio_array_t *a, // I - Array
|
||||
pdfio_obj_t *obj) // I - Object, if any
|
||||
{
|
||||
pdfio_file_t *pdf = a->pdf; // PDF file
|
||||
size_t i; // Looping var
|
||||
_pdfio_value_t *v; // Current value
|
||||
|
||||
|
||||
// Arrays are surrounded by square brackets ([ ... ])
|
||||
if (!(cb)(cbdata, "["))
|
||||
if (!_pdfioFilePuts(pdf, "["))
|
||||
return (false);
|
||||
|
||||
// Write each value...
|
||||
for (i = a->num_values, v = a->values; i > 0; i --, v ++)
|
||||
{
|
||||
if (!_pdfioValueWrite(cb, cbdata, obj, v, NULL))
|
||||
if (!_pdfioValueWrite(pdf, obj, v, NULL))
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Closing bracket...
|
||||
return ((cb)(cbdata, "]"));
|
||||
return (_pdfioFilePuts(pdf, "]"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,532 +0,0 @@
|
||||
/* CGATS001Compat-v2-micro.icc */
|
||||
static unsigned char CGATS001Compat_v2_micro_icc[] = {
|
||||
0,0,33,16,65,68,66,69,2,16,0,0,115,99,110,114,
|
||||
67,77,89,75,76,97,98,32,7,230,0,12,0,7,0,22,
|
||||
0,16,0,42,97,99,115,112,77,83,70,84,0,0,0,0,
|
||||
115,97,119,115,99,116,114,108,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,246,214,0,1,0,0,0,0,211,45,
|
||||
104,97,110,100,195,103,209,209,26,217,105,182,62,57,156,48,
|
||||
22,179,165,88,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,4,100,101,115,99,0,0,0,180,0,0,0,95,
|
||||
99,112,114,116,0,0,0,208,0,0,0,12,119,116,112,116,
|
||||
0,0,0,220,0,0,0,20,65,50,66,48,0,0,0,240,
|
||||
0,0,32,32,100,101,115,99,0,0,0,0,0,0,0,5,
|
||||
117,67,77,89,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
116,101,120,116,0,0,0,0,67,67,48,0,88,89,90,32,
|
||||
0,0,0,0,0,0,246,214,0,1,0,0,0,0,211,45,
|
||||
109,102,116,50,0,0,0,0,4,3,6,0,0,1,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
|
||||
0,48,0,2,0,0,10,35,16,0,22,155,28,150,35,8,
|
||||
41,37,47,68,53,83,59,90,65,90,71,78,77,74,83,48,
|
||||
89,25,94,245,100,188,106,133,112,43,117,193,123,79,128,187,
|
||||
134,23,139,107,144,166,149,206,154,244,160,21,165,30,170,40,
|
||||
175,51,180,64,185,71,190,81,195,91,200,103,205,100,210,85,
|
||||
215,65,220,33,224,252,229,190,234,87,238,218,243,138,248,23,
|
||||
252,104,255,255,0,0,8,214,13,206,19,98,24,129,30,6,
|
||||
35,77,40,160,46,0,51,86,56,193,62,41,67,165,73,37,
|
||||
78,162,84,51,89,175,95,46,100,173,106,10,111,107,116,191,
|
||||
121,244,127,36,132,82,137,98,142,111,147,127,152,147,157,151,
|
||||
162,172,167,211,173,14,178,88,183,186,189,52,194,199,200,90,
|
||||
205,244,211,154,217,72,223,1,228,146,234,19,239,215,245,132,
|
||||
251,7,255,255,0,0,9,30,14,44,19,200,24,222,30,99,
|
||||
35,150,40,200,45,246,51,35,56,84,61,138,66,209,72,33,
|
||||
77,126,82,234,88,89,93,211,99,74,104,190,110,47,115,148,
|
||||
120,237,126,59,131,126,136,180,141,231,147,29,152,90,157,169,
|
||||
163,18,168,158,174,79,180,41,186,39,192,69,198,114,204,164,
|
||||
210,199,216,201,222,161,228,73,233,160,238,170,243,244,248,186,
|
||||
252,225,255,255,0,0,8,135,13,57,18,115,23,60,28,123,
|
||||
33,106,38,94,43,92,48,99,53,110,58,133,63,163,68,202,
|
||||
73,244,79,35,84,77,89,109,94,139,99,158,104,170,109,176,
|
||||
114,172,119,156,124,135,129,112,134,74,139,35,143,254,148,223,
|
||||
153,201,158,194,163,209,168,251,174,67,179,163,185,36,190,202,
|
||||
196,145,202,125,208,133,214,166,220,240,227,93,234,118,241,193,
|
||||
249,40,255,255,255,0,128,0,128,0,214,110,127,181,126,251,
|
||||
173,86,127,150,126,88,131,53,127,186,126,83,86,78,128,50,
|
||||
126,192,31,100,129,254,128,28,251,120,125,171,146,104,211,247,
|
||||
125,155,142,161,171,46,125,194,139,106,129,32,126,37,136,221,
|
||||
84,57,126,196,134,230,28,170,128,62,134,99,248,103,123,237,
|
||||
165,11,209,76,123,249,158,148,168,209,124,68,152,192,127,22,
|
||||
124,213,147,218,82,110,125,139,143,116,26,73,126,145,140,106,
|
||||
245,211,122,201,183,251,206,211,122,205,174,205,166,160,123,35,
|
||||
166,133,125,42,123,200,159,52,80,217,124,141,151,243,24,82,
|
||||
125,10,144,4,243,199,122,9,203,97,204,207,121,247,191,95,
|
||||
164,205,122,74,180,169,123,179,123,1,171,70,79,144,123,201,
|
||||
163,159,22,200,123,191,143,103,242,42,121,140,223,132,203,50,
|
||||
121,98,208,125,163,73,121,169,195,108,122,115,122,107,184,86,
|
||||
78,150,123,56,174,96,21,158,122,200,142,157,227,233,142,168,
|
||||
125,57,191,208,140,54,124,173,154,204,138,30,124,141,116,50,
|
||||
136,124,124,247,74,84,135,121,125,199,20,34,137,177,127,236,
|
||||
224,239,140,172,141,230,189,193,138,73,138,227,152,241,136,91,
|
||||
136,116,114,87,134,238,134,171,72,129,134,18,133,143,18,45,
|
||||
135,202,133,165,222,108,139,13,159,8,187,88,136,200,153,179,
|
||||
150,192,134,245,148,251,112,129,133,173,145,24,70,249,132,229,
|
||||
142,34,16,97,134,27,137,235,220,58,137,245,176,93,185,57,
|
||||
135,184,168,203,148,204,133,239,161,238,110,212,132,170,155,243,
|
||||
69,169,131,235,151,169,15,9,132,165,138,43,218,113,137,45,
|
||||
194,46,183,137,134,242,184,87,147,63,133,43,175,95,109,144,
|
||||
131,243,167,166,68,161,131,41,161,166,14,7,131,135,137,124,
|
||||
217,12,136,152,212,229,182,53,134,99,200,164,145,250,132,152,
|
||||
189,153,108,133,131,103,180,155,67,209,130,165,170,33,13,68,
|
||||
130,183,136,248,201,213,157,235,123,46,169,121,153,123,122,234,
|
||||
136,53,149,117,123,19,101,12,146,14,123,193,62,13,143,191,
|
||||
124,214,9,84,144,204,127,187,199,84,156,73,138,107,167,205,
|
||||
151,198,136,7,134,185,147,217,134,42,99,150,144,153,132,246,
|
||||
60,167,142,98,132,135,8,113,142,126,132,36,197,113,154,202,
|
||||
153,237,165,235,150,98,149,123,132,247,146,119,145,165,98,4,
|
||||
143,82,142,167,59,93,141,42,140,19,7,182,140,158,133,55,
|
||||
195,166,153,193,169,229,164,50,149,94,163,134,131,66,145,135,
|
||||
157,217,96,149,142,92,153,26,58,81,140,51,150,79,7,25,
|
||||
139,41,132,204,194,42,153,10,186,48,162,214,148,166,177,236,
|
||||
129,253,144,210,170,123,95,138,141,175,164,116,57,139,139,110,
|
||||
159,13,6,174,138,21,132,132,192,255,152,123,203,106,161,198,
|
||||
148,25,193,44,128,245,144,72,184,9,94,179,141,45,177,103,
|
||||
56,235,138,244,165,100,6,89,137,77,132,75,177,37,173,245,
|
||||
122,2,147,243,167,169,121,209,117,242,161,206,122,23,85,235,
|
||||
156,180,122,225,49,88,150,201,124,2,0,239,149,92,127,195,
|
||||
175,57,172,141,135,237,146,202,166,25,133,179,116,224,160,67,
|
||||
132,66,84,210,155,60,131,120,48,93,152,11,131,193,0,226,
|
||||
147,96,128,133,173,202,171,58,150,19,145,79,164,217,146,68,
|
||||
115,118,159,2,143,29,83,154,154,5,140,217,47,124,150,201,
|
||||
140,54,0,206,145,182,128,139,172,145,170,52,164,133,144,19,
|
||||
163,219,159,13,114,58,158,5,154,89,82,143,152,241,150,198,
|
||||
46,202,149,168,148,235,0,217,144,85,128,147,171,106,169,130,
|
||||
179,137,143,32,163,20,172,85,113,80,157,63,162,160,81,202,
|
||||
152,62,161,248,46,73,148,212,155,139,0,219,143,72,128,148,
|
||||
170,119,169,1,195,84,142,87,162,131,186,91,112,151,156,179,
|
||||
178,242,81,58,151,186,174,21,45,236,148,82,159,13,0,222,
|
||||
142,134,128,150,154,49,190,221,121,79,127,198,182,195,121,6,
|
||||
100,136,175,54,121,74,71,42,168,146,122,23,36,45,165,99,
|
||||
123,14,0,0,143,153,128,0,152,249,189,121,134,22,127,13,
|
||||
181,72,132,75,99,211,173,165,130,235,70,115,166,244,130,111,
|
||||
35,202,163,124,130,239,0,0,142,213,128,0,152,46,188,21,
|
||||
146,252,126,42,179,238,143,148,98,240,172,64,140,239,69,182,
|
||||
165,143,139,90,35,118,161,226,138,239,0,0,142,33,128,0,
|
||||
151,95,187,20,156,183,125,105,178,222,152,248,98,53,171,44,
|
||||
148,44,69,34,164,102,145,119,35,60,160,141,143,228,0,0,
|
||||
141,150,128,0,150,186,186,65,173,194,124,235,177,250,167,108,
|
||||
97,205,170,70,162,133,68,210,163,131,159,209,35,33,159,106,
|
||||
150,67,0,0,141,57,128,0,150,10,185,176,188,68,124,138,
|
||||
177,69,180,40,97,126,169,128,174,82,68,159,162,198,170,52,
|
||||
35,38,158,179,151,196,0,0,140,230,128,0,132,180,208,159,
|
||||
120,243,108,190,198,205,120,107,83,203,189,201,120,144,56,144,
|
||||
181,241,121,63,22,242,178,158,122,81,0,0,137,249,128,0,
|
||||
132,84,206,246,132,213,108,102,197,80,130,218,83,105,188,24,
|
||||
129,168,56,75,180,0,129,93,23,73,176,8,130,10,0,0,
|
||||
138,37,128,0,132,67,205,78,144,147,108,56,195,164,141,107,
|
||||
83,48,186,79,139,41,56,52,178,35,138,58,23,180,173,196,
|
||||
137,41,0,0,138,73,128,0,132,35,203,251,156,155,108,55,
|
||||
194,41,152,56,83,60,184,196,149,21,56,85,176,133,148,4,
|
||||
24,42,171,234,144,154,0,0,138,101,128,0,131,240,202,242,
|
||||
168,242,108,66,193,0,163,54,83,110,183,140,159,100,56,150,
|
||||
175,80,157,234,24,158,170,120,144,165,0,0,138,121,128,0,
|
||||
131,190,202,18,181,197,108,88,192,13,174,136,83,181,182,138,
|
||||
170,24,56,250,174,76,165,33,25,38,169,99,145,1,0,0,
|
||||
138,136,128,0,235,21,120,95,117,172,198,143,121,103,118,146,
|
||||
160,155,122,106,119,154,120,244,123,117,120,218,78,61,124,157,
|
||||
122,46,24,103,126,52,123,43,231,220,117,150,135,222,195,241,
|
||||
118,230,133,232,158,88,120,46,132,101,118,244,121,124,131,68,
|
||||
76,100,122,195,129,102,22,11,123,166,130,96,228,245,115,130,
|
||||
154,56,193,46,116,236,149,151,155,232,118,93,145,116,116,232,
|
||||
119,221,141,248,74,174,121,54,138,229,19,252,121,133,135,196,
|
||||
226,139,114,5,172,159,190,208,115,112,165,140,153,177,116,238,
|
||||
158,247,114,251,118,134,153,19,73,38,119,231,148,52,18,94,
|
||||
119,220,139,241,224,194,113,11,191,52,189,12,114,105,181,200,
|
||||
151,244,115,224,172,209,113,127,117,135,164,211,71,234,118,225,
|
||||
158,108,17,36,118,168,139,151,223,129,112,120,210,33,187,195,
|
||||
113,192,198,94,150,146,115,32,187,38,112,68,116,200,177,102,
|
||||
70,235,118,28,168,223,16,59,117,202,138,249,209,115,134,135,
|
||||
115,123,177,87,133,101,116,211,143,52,132,136,118,40,106,212,
|
||||
131,237,119,166,66,203,131,210,121,44,13,68,133,161,122,166,
|
||||
207,74,132,21,132,44,175,136,131,38,130,252,141,102,130,108,
|
||||
130,15,105,23,129,246,129,111,65,44,129,242,129,3,11,242,
|
||||
131,47,128,187,204,230,130,32,148,250,173,11,129,68,145,118,
|
||||
139,42,128,171,142,60,103,60,128,104,139,143,63,171,128,112,
|
||||
137,123,10,160,129,38,133,169,202,204,128,181,165,229,170,253,
|
||||
127,222,160,68,137,59,127,80,154,224,101,154,127,25,150,30,
|
||||
62,106,127,39,146,206,9,181,127,147,134,144,201,66,127,194,
|
||||
183,38,169,111,126,232,175,109,135,176,126,82,167,231,100,77,
|
||||
126,40,161,100,61,104,126,40,156,138,9,4,126,105,134,24,
|
||||
200,52,127,42,201,23,168,66,126,72,191,65,134,106,125,151,
|
||||
181,160,99,54,125,111,173,200,60,152,125,113,164,221,8,120,
|
||||
125,143,133,186,184,173,149,106,113,228,156,34,146,61,115,98,
|
||||
125,114,143,136,116,221,92,54,141,74,118,127,54,161,140,45,
|
||||
120,8,3,238,139,88,123,49,182,255,147,72,129,49,154,137,
|
||||
144,64,128,123,123,227,141,162,127,240,90,199,139,126,127,190,
|
||||
53,89,138,93,127,196,3,128,136,228,128,74,181,64,145,117,
|
||||
144,98,152,169,142,132,141,169,122,46,139,240,139,55,89,77,
|
||||
137,236,137,71,52,47,136,204,136,38,3,22,134,234,130,22,
|
||||
179,141,144,32,160,3,151,4,141,51,155,112,120,129,138,173,
|
||||
151,29,87,228,136,172,147,114,51,37,135,135,145,82,2,193,
|
||||
133,95,129,221,178,73,143,62,175,217,149,185,140,83,169,123,
|
||||
119,61,137,196,163,94,86,209,135,201,158,101,50,96,134,132,
|
||||
153,234,2,137,132,59,129,182,177,102,142,167,192,110,148,187,
|
||||
139,188,184,74,118,48,137,28,176,117,85,236,135,30,170,208,
|
||||
49,180,133,217,160,46,2,88,131,104,129,150,161,39,165,31,
|
||||
112,232,135,104,160,39,114,94,107,178,155,186,115,225,77,78,
|
||||
151,243,117,130,41,135,150,141,118,177,0,66,137,171,126,52,
|
||||
160,0,163,78,126,58,134,90,158,94,125,202,106,159,153,235,
|
||||
126,68,76,76,150,41,126,114,40,187,148,150,126,116,0,60,
|
||||
135,218,127,249,158,179,161,163,140,195,132,230,156,194,138,139,
|
||||
105,69,152,84,136,161,75,40,148,163,135,100,39,242,146,245,
|
||||
134,224,0,50,134,74,128,34,157,132,160,84,154,226,131,173,
|
||||
155,126,151,25,104,13,151,13,147,166,74,49,147,72,145,0,
|
||||
39,88,145,123,143,118,0,46,133,35,128,31,156,138,159,124,
|
||||
169,118,130,195,154,160,164,33,103,23,150,32,159,51,73,88,
|
||||
146,97,155,208,38,210,144,100,150,43,0,40,132,62,128,27,
|
||||
155,211,158,242,184,169,130,0,154,13,177,217,102,77,149,124,
|
||||
171,165,72,175,145,184,167,171,38,95,143,176,153,237,0,36,
|
||||
131,152,128,24,139,20,181,218,112,19,115,151,175,83,113,97,
|
||||
90,95,169,85,114,209,62,89,164,67,116,78,27,220,162,240,
|
||||
117,20,0,0,132,76,128,0,138,120,180,61,125,106,115,25,
|
||||
173,150,124,255,89,217,167,107,124,81,61,228,162,62,124,151,
|
||||
27,203,160,109,125,6,0,0,131,187,128,0,137,192,178,136,
|
||||
137,145,114,53,171,233,135,226,88,255,165,185,134,144,61,56,
|
||||
160,141,133,174,27,150,158,104,133,23,0,0,131,37,128,0,
|
||||
136,247,177,65,150,121,113,106,170,160,145,137,88,50,164,101,
|
||||
144,140,60,162,159,30,142,229,27,110,156,173,140,81,0,0,
|
||||
130,194,128,0,136,101,176,88,163,151,112,222,169,174,159,42,
|
||||
87,167,163,100,155,105,60,52,158,16,153,106,27,92,155,60,
|
||||
144,208,0,0,130,140,128,0,135,225,175,208,177,149,112,130,
|
||||
169,4,171,225,87,60,162,144,167,47,59,221,157,49,163,199,
|
||||
27,68,154,81,146,112,0,0,130,90,128,0,118,47,199,165,
|
||||
111,81,96,137,191,214,112,85,73,93,184,132,113,146,47,37,
|
||||
178,156,114,188,14,114,176,12,115,215,0,0,129,66,128,0,
|
||||
118,37,198,9,123,103,96,145,189,252,122,224,73,95,182,83,
|
||||
122,140,47,79,176,27,122,242,15,16,173,6,123,149,0,0,
|
||||
129,65,128,0,118,26,196,25,134,225,96,81,188,12,133,19,
|
||||
73,32,180,78,131,219,47,67,173,249,131,127,15,152,170,90,
|
||||
131,15,0,0,129,64,128,0,117,232,194,153,146,128,96,44,
|
||||
186,112,143,187,72,249,178,157,141,124,47,72,172,34,141,8,
|
||||
16,17,168,31,136,88,0,0,129,63,128,0,117,180,193,153,
|
||||
158,127,96,36,185,65,154,198,72,250,177,80,152,1,47,90,
|
||||
170,197,151,16,16,120,166,98,139,34,0,0,129,63,128,0,
|
||||
117,138,192,236,171,6,96,44,184,93,166,88,73,12,176,73,
|
||||
163,22,47,127,169,175,158,184,16,201,165,41,139,89,0,0,
|
||||
129,62,128,0,215,58,112,125,107,98,182,48,114,183,110,9,
|
||||
147,81,116,191,112,146,110,79,118,168,115,18,69,242,120,110,
|
||||
117,99,17,41,122,4,118,21,212,37,109,25,125,61,179,174,
|
||||
111,175,125,19,145,41,114,6,125,27,108,110,116,58,125,82,
|
||||
68,67,118,17,125,118,15,115,119,100,124,211,209,76,106,99,
|
||||
143,18,176,232,109,33,140,81,142,189,111,175,137,216,106,111,
|
||||
114,31,135,215,66,173,115,252,133,236,14,12,117,65,131,106,
|
||||
206,240,104,112,160,225,174,148,107,62,155,216,140,130,109,225,
|
||||
150,255,104,143,112,110,146,160,65,64,114,73,142,92,12,238,
|
||||
115,154,136,44,205,74,103,27,178,184,172,233,105,229,171,138,
|
||||
138,211,108,132,164,100,103,24,111,33,157,249,64,30,112,232,
|
||||
153,0,12,32,114,96,136,51,204,67,102,85,196,179,171,201,
|
||||
105,11,187,103,137,134,107,139,178,19,101,232,110,39,169,242,
|
||||
63,37,113,29,163,2,11,134,113,150,135,202,191,51,125,253,
|
||||
105,204,162,88,126,40,108,203,130,244,126,117,111,124,96,224,
|
||||
126,227,114,20,58,181,127,161,116,87,6,250,129,135,117,232,
|
||||
189,59,122,243,122,101,160,121,123,114,122,237,129,38,123,241,
|
||||
123,66,95,70,124,136,123,210,57,87,125,61,124,104,6,56,
|
||||
126,240,124,161,186,231,120,104,138,147,158,7,121,10,136,216,
|
||||
126,247,121,180,135,50,93,119,122,128,133,202,55,236,123,44,
|
||||
132,147,5,122,125,75,129,223,184,229,118,148,155,6,156,7,
|
||||
119,69,151,69,125,15,119,255,147,122,91,227,120,220,144,16,
|
||||
54,189,121,122,141,190,4,240,123,230,131,75,183,122,117,78,
|
||||
171,160,154,140,117,255,165,231,123,150,118,180,160,18,90,158,
|
||||
119,159,154,248,53,206,120,29,151,54,4,139,123,11,131,18,
|
||||
182,151,116,140,188,154,153,124,117,45,180,249,122,105,117,198,
|
||||
173,42,89,148,118,175,166,195,52,247,119,27,159,91,4,58,
|
||||
122,75,130,219,168,10,140,102,104,152,142,157,138,129,107,167,
|
||||
114,84,137,23,110,98,83,5,136,13,112,248,46,178,136,50,
|
||||
114,232,0,0,134,1,119,195,166,152,137,165,119,142,140,252,
|
||||
136,21,120,113,112,187,134,199,121,68,81,165,133,209,122,43,
|
||||
45,147,133,199,122,111,0,0,131,203,125,115,164,228,135,58,
|
||||
134,91,139,30,133,208,133,102,111,24,132,156,132,87,80,93,
|
||||
131,190,131,134,44,163,131,149,130,248,0,0,129,242,128,0,
|
||||
163,51,133,129,149,157,137,135,132,33,146,220,109,118,130,247,
|
||||
143,243,78,252,130,37,141,109,43,168,129,222,139,252,0,0,
|
||||
128,80,128,0,162,3,132,83,164,223,136,69,130,249,160,109,
|
||||
108,52,129,194,155,194,77,229,128,243,151,242,42,242,128,117,
|
||||
148,112,0,0,128,0,128,0,161,66,131,152,180,173,135,81,
|
||||
130,59,174,155,107,41,128,225,168,60,77,1,128,10,163,180,
|
||||
42,74,127,120,154,175,0,0,128,0,128,0,145,188,155,172,
|
||||
103,193,122,194,152,25,106,174,97,34,149,28,109,90,68,88,
|
||||
146,185,111,205,33,58,147,6,113,3,0,0,128,158,125,23,
|
||||
144,178,153,85,117,117,121,161,149,241,118,113,96,7,146,235,
|
||||
119,201,67,104,144,128,120,192,32,163,144,90,120,208,0,0,
|
||||
128,83,127,160,143,100,151,24,131,16,120,32,147,209,130,146,
|
||||
94,175,144,218,130,3,66,85,142,130,129,188,32,1,142,10,
|
||||
128,235,0,0,128,0,128,0,142,45,149,108,144,194,118,226,
|
||||
146,54,142,170,93,120,143,61,140,135,65,117,140,210,138,222,
|
||||
31,136,140,18,137,181,0,0,128,0,128,0,141,62,148,80,
|
||||
158,204,117,254,145,26,155,76,92,129,142,10,151,180,64,146,
|
||||
139,158,149,70,31,15,138,141,145,227,0,0,128,0,128,0,
|
||||
140,159,147,161,173,59,117,64,144,98,168,119,91,182,141,51,
|
||||
163,160,63,227,138,184,160,184,30,155,137,127,148,146,0,0,
|
||||
128,0,128,0,124,171,172,10,102,190,103,126,167,39,105,111,
|
||||
80,11,162,201,107,245,53,57,159,120,110,24,19,165,158,208,
|
||||
111,20,0,0,128,0,128,0,123,249,170,24,116,224,102,230,
|
||||
165,24,117,140,79,132,160,128,117,94,52,226,156,255,118,88,
|
||||
19,187,155,193,119,9,0,0,128,0,128,0,123,42,167,228,
|
||||
127,253,101,234,162,244,127,85,78,167,158,94,127,12,52,67,
|
||||
154,215,126,238,19,159,153,39,127,38,0,0,128,0,128,0,
|
||||
122,87,166,68,140,182,101,22,161,89,139,59,77,209,156,183,
|
||||
137,52,51,180,153,17,136,91,19,135,150,246,134,122,0,0,
|
||||
128,0,128,0,121,194,165,30,152,238,100,130,160,44,150,73,
|
||||
77,54,155,119,147,192,51,58,151,189,146,136,19,131,149,48,
|
||||
139,58,0,0,128,0,128,0,121,80,164,119,166,54,100,51,
|
||||
159,99,162,165,76,201,154,118,159,46,50,220,150,162,156,195,
|
||||
19,98,147,245,141,27,0,0,128,0,128,0,104,127,189,181,
|
||||
101,120,84,142,183,253,103,201,62,206,178,149,106,4,37,57,
|
||||
175,32,107,133,7,201,168,185,110,103,0,0,128,0,128,0,
|
||||
104,19,188,17,113,56,84,117,181,220,113,249,62,221,175,253,
|
||||
114,239,37,150,172,20,115,158,8,71,165,174,118,13,0,0,
|
||||
128,0,128,0,103,206,185,191,124,128,84,14,179,133,124,35,
|
||||
62,146,173,145,124,7,37,152,169,115,124,23,8,149,163,10,
|
||||
125,3,0,0,128,0,128,0,103,132,183,243,135,237,83,215,
|
||||
177,160,134,186,62,83,171,151,133,157,37,151,167,69,133,155,
|
||||
8,210,160,225,134,24,0,0,128,0,128,0,103,71,182,193,
|
||||
147,197,83,203,176,53,145,186,62,65,170,12,143,228,37,150,
|
||||
165,157,143,124,9,4,159,47,134,25,0,0,128,0,128,0,
|
||||
103,34,182,5,159,118,83,218,175,42,156,247,62,66,168,216,
|
||||
154,228,37,162,164,81,151,207,9,28,157,237,134,41,0,0,
|
||||
128,0,128,0,195,134,104,39,97,50,165,143,107,98,101,100,
|
||||
133,177,110,87,105,86,99,107,113,26,109,23,61,117,115,78,
|
||||
112,105,10,197,118,146,113,155,192,120,99,196,114,159,163,37,
|
||||
103,127,116,32,131,159,106,221,117,164,97,161,109,247,119,42,
|
||||
59,237,112,35,120,108,9,208,115,227,120,197,189,150,96,56,
|
||||
131,182,160,101,100,60,130,212,129,66,103,227,130,4,95,178,
|
||||
107,69,129,80,58,117,109,94,128,220,8,252,114,54,127,181,
|
||||
187,44,93,116,149,0,158,28,97,167,145,220,127,29,101,119,
|
||||
142,191,93,247,105,0,139,222,57,48,106,248,136,228,8,98,
|
||||
114,207,133,15,185,130,91,150,166,49,156,129,95,216,160,239,
|
||||
125,137,99,178,155,159,92,152,103,80,150,226,56,49,105,27,
|
||||
147,108,7,231,114,249,133,88,184,132,90,105,183,86,155,115,
|
||||
94,161,175,238,124,98,98,101,168,131,91,140,105,1,162,44,
|
||||
55,84,103,155,156,250,7,143,115,57,133,29,173,93,116,242,
|
||||
96,48,147,55,118,74,100,152,118,92,119,176,104,140,86,142,
|
||||
121,30,108,57,50,50,122,128,111,45,2,87,126,109,114,86,
|
||||
171,85,112,240,112,28,145,91,114,194,114,35,116,164,116,109,
|
||||
115,251,85,28,118,12,117,186,49,17,119,53,119,0,2,43,
|
||||
125,195,121,110,168,240,109,150,128,2,142,230,111,169,127,232,
|
||||
114,129,113,144,127,187,83,92,115,109,127,135,47,194,116,98,
|
||||
127,74,1,226,125,94,127,32,166,228,106,254,143,238,140,233,
|
||||
109,54,141,221,112,164,111,63,139,156,81,229,113,51,137,125,
|
||||
46,184,113,233,136,69,1,188,125,70,129,22,165,119,105,58,
|
||||
159,231,139,118,107,126,155,238,111,59,109,141,151,183,80,175,
|
||||
111,144,148,16,45,231,112,10,145,123,1,153,125,77,129,20,
|
||||
164,153,104,24,176,2,138,114,106,82,170,42,110,35,111,42,
|
||||
164,16,79,186,110,75,159,42,45,29,110,151,153,133,1,123,
|
||||
125,127,129,0,151,185,130,155,95,107,128,155,130,26,99,200,
|
||||
102,131,129,250,103,171,73,25,130,36,107,48,37,224,131,72,
|
||||
109,106,0,0,128,15,119,32,150,37,126,232,109,252,126,233,
|
||||
126,222,112,71,100,238,126,239,114,85,71,211,127,49,116,50,
|
||||
36,254,127,224,117,40,0,0,128,0,125,1,148,89,123,191,
|
||||
124,214,124,252,123,247,125,43,99,88,124,49,125,116,70,157,
|
||||
124,147,125,171,36,61,124,241,125,162,0,0,128,0,128,0,
|
||||
146,160,121,84,139,48,123,96,121,170,138,25,97,182,121,248,
|
||||
136,132,69,80,122,100,134,203,35,88,122,135,134,48,0,0,
|
||||
128,0,128,0,145,107,119,175,153,210,122,36,120,16,150,250,
|
||||
96,132,120,91,147,207,68,71,120,200,145,64,34,188,120,174,
|
||||
142,195,0,0,128,0,128,0,144,162,120,93,168,186,121,57,
|
||||
120,129,164,90,95,144,120,148,159,155,67,117,120,204,156,88,
|
||||
34,21,119,83,148,183,0,0,128,0,128,0,130,198,145,99,
|
||||
94,162,109,209,143,77,98,193,86,12,141,196,102,123,58,184,
|
||||
140,221,105,176,24,115,141,200,107,28,0,0,128,0,124,73,
|
||||
129,132,142,31,107,235,108,146,140,92,110,64,84,240,138,218,
|
||||
113,211,57,230,137,229,115,138,24,36,138,59,114,239,0,0,
|
||||
128,0,127,132,128,22,139,40,121,37,107,6,137,153,122,194,
|
||||
83,165,136,48,123,82,56,243,135,70,123,12,23,189,135,58,
|
||||
123,75,0,0,128,0,128,0,126,190,136,215,135,50,105,197,
|
||||
135,98,134,150,82,127,133,248,133,151,56,76,132,242,133,17,
|
||||
23,130,132,161,132,185,0,0,128,0,128,0,125,190,135,83,
|
||||
147,232,104,226,133,228,145,251,81,131,132,98,143,208,55,90,
|
||||
131,82,142,43,23,27,130,174,140,195,0,0,128,0,128,0,
|
||||
125,14,134,79,161,162,104,29,132,220,158,145,80,187,131,56,
|
||||
154,254,54,173,130,12,153,42,22,191,129,62,143,48,0,0,
|
||||
128,0,128,0,110,138,161,103,93,113,91,64,158,36,97,61,
|
||||
69,98,155,115,100,180,43,134,154,24,103,87,11,238,152,5,
|
||||
105,90,0,0,128,0,127,174,109,133,158,164,105,164,90,112,
|
||||
155,103,107,227,68,195,152,129,109,252,43,62,150,221,111,137,
|
||||
12,25,148,105,113,67,0,0,128,0,128,0,108,132,155,200,
|
||||
117,179,89,77,152,172,118,164,67,211,149,207,119,119,42,162,
|
||||
148,24,120,5,12,19,145,67,121,90,0,0,128,0,128,0,
|
||||
107,134,153,143,129,221,88,92,150,130,129,173,66,235,147,154,
|
||||
129,73,42,24,145,180,129,15,12,0,142,157,128,215,0,0,
|
||||
128,0,128,0,106,209,152,11,143,26,87,176,149,0,141,197,
|
||||
66,62,146,3,140,0,41,140,143,253,139,52,12,1,140,140,
|
||||
133,216,0,0,128,0,128,0,106,74,151,18,154,199,87,83,
|
||||
147,243,152,208,65,214,144,186,150,118,41,61,142,132,149,10,
|
||||
11,233,139,8,136,14,0,0,128,0,128,0,90,217,179,10,
|
||||
91,159,72,146,175,35,94,239,52,17,171,191,97,242,26,122,
|
||||
171,135,99,103,2,147,158,4,105,195,0,0,128,0,128,0,
|
||||
89,242,176,188,102,234,72,22,172,122,104,233,51,223,168,163,
|
||||
106,202,26,208,167,186,107,134,3,13,154,120,113,121,0,0,
|
||||
128,0,128,0,89,104,173,222,113,237,71,119,169,158,114,221,
|
||||
51,113,165,180,115,185,26,205,164,114,115,225,3,91,151,84,
|
||||
119,101,0,0,128,0,128,0,88,225,171,136,125,19,71,16,
|
||||
167,63,125,46,51,16,163,58,125,29,26,204,161,154,125,2,
|
||||
3,150,148,166,126,188,0,0,128,0,128,0,88,127,169,250,
|
||||
136,100,70,230,165,137,135,210,50,233,161,96,135,19,26,190,
|
||||
159,136,135,59,3,199,146,155,130,61,0,0,128,0,128,0,
|
||||
88,66,168,239,147,235,70,221,164,67,146,236,50,224,159,237,
|
||||
145,204,26,206,157,221,143,133,3,222,145,7,130,157,0,0,
|
||||
128,0,128,0,176,156,94,195,87,72,149,115,98,233,92,217,
|
||||
120,99,102,205,98,34,88,182,106,104,103,28,53,1,108,159,
|
||||
107,102,5,152,118,139,109,251,173,120,88,199,104,44,147,0,
|
||||
93,173,107,60,118,78,98,35,110,48,86,244,102,42,113,1,
|
||||
51,155,104,36,115,88,5,62,119,36,117,123,170,129,83,218,
|
||||
120,230,144,69,89,66,121,155,116,3,94,37,122,79,85,27,
|
||||
98,129,123,12,50,72,100,77,123,164,4,235,119,176,124,186,
|
||||
167,244,79,239,137,125,142,8,85,186,136,49,114,1,90,231,
|
||||
134,220,83,144,95,120,133,94,49,50,97,23,132,122,4,171,
|
||||
120,27,130,105,166,29,76,244,153,245,140,119,83,4,150,99,
|
||||
112,161,88,98,146,223,82,98,93,18,143,209,48,103,94,148,
|
||||
141,222,4,128,120,101,131,11,165,1,75,27,170,73,139,111,
|
||||
81,61,164,132,111,168,86,158,159,0,81,141,91,86,154,125,
|
||||
47,181,92,180,151,6,4,90,120,165,130,241,156,106,106,192,
|
||||
86,220,132,107,109,76,92,113,105,223,111,205,97,148,76,63,
|
||||
114,46,102,77,41,113,115,222,105,208,0,133,127,32,112,194,
|
||||
154,6,101,52,102,67,130,120,104,112,105,168,104,51,107,92,
|
||||
108,201,74,235,109,253,111,166,40,136,111,123,113,155,0,121,
|
||||
127,52,119,248,151,123,96,136,117,195,127,250,100,52,119,22,
|
||||
102,27,103,124,120,55,73,62,106,97,121,62,39,94,107,182,
|
||||
121,207,0,101,127,85,125,231,149,85,92,216,133,116,125,254,
|
||||
96,208,133,45,100,78,100,86,131,234,71,229,103,88,131,7,
|
||||
38,123,104,160,130,168,0,90,127,104,128,21,147,206,90,13,
|
||||
148,102,124,145,94,51,145,245,98,253,97,219,143,75,70,199,
|
||||
100,234,141,18,37,213,102,40,139,156,0,82,127,118,128,55,
|
||||
146,221,88,74,163,183,123,146,92,123,159,112,97,255,96,28,
|
||||
154,247,69,241,99,40,151,144,37,38,100,94,147,151,0,74,
|
||||
127,132,128,50,136,83,119,164,86,119,114,249,120,152,91,224,
|
||||
90,200,121,197,96,207,63,24,123,14,101,47,28,228,124,239,
|
||||
103,177,0,0,128,0,118,153,134,86,114,117,100,134,113,39,
|
||||
116,9,104,12,89,55,117,132,107,62,61,232,118,232,110,10,
|
||||
28,63,120,131,111,111,0,0,128,0,124,173,132,83,110,13,
|
||||
114,153,111,34,112,8,116,89,87,166,113,196,117,216,60,195,
|
||||
115,69,119,23,27,177,116,190,119,163,0,0,128,0,128,0,
|
||||
130,119,106,149,129,11,109,119,108,205,130,35,86,4,110,179,
|
||||
128,158,59,134,112,55,128,143,26,244,113,202,129,140,0,0,
|
||||
128,0,128,0,129,36,103,242,142,177,108,51,106,79,140,179,
|
||||
84,214,108,70,139,126,58,135,109,187,138,52,26,128,111,130,
|
||||
137,83,0,0,128,0,128,0,128,71,102,62,157,11,107,73,
|
||||
104,167,154,28,83,238,106,146,150,196,57,196,107,241,148,173,
|
||||
25,237,109,244,142,180,0,0,128,0,128,0,116,102,133,188,
|
||||
85,206,97,9,133,77,90,232,74,225,133,71,95,143,48,197,
|
||||
133,211,99,100,15,223,135,31,101,112,0,0,128,0,123,165,
|
||||
114,183,129,2,98,152,95,147,129,17,102,24,73,174,129,44,
|
||||
105,65,47,247,129,153,107,201,15,177,130,194,109,55,0,0,
|
||||
128,0,127,79,113,14,124,224,111,119,93,220,125,64,113,115,
|
||||
72,73,125,135,115,40,46,243,125,235,116,107,15,86,127,106,
|
||||
117,126,0,0,128,0,128,0,111,138,121,149,124,88,92,114,
|
||||
122,42,124,241,71,9,122,128,125,56,46,66,122,185,125,99,
|
||||
15,42,124,159,125,207,0,0,128,0,128,0,110,95,119,23,
|
||||
138,202,91,117,119,207,138,10,70,19,120,28,137,0,45,94,
|
||||
120,38,135,245,14,222,122,140,135,102,0,0,128,0,128,0,
|
||||
109,149,121,89,150,108,90,170,121,119,148,158,69,84,118,115,
|
||||
146,87,44,190,118,78,145,129,14,137,120,225,137,87,0,0,
|
||||
128,0,128,0,96,221,149,113,84,82,79,24,147,218,89,8,
|
||||
58,133,146,240,93,68,32,234,148,5,96,5,5,223,142,72,
|
||||
100,242,0,0,128,0,127,76,95,109,145,55,96,1,77,234,
|
||||
143,234,99,97,57,154,142,232,102,93,32,131,143,118,104,29,
|
||||
6,7,138,144,108,199,0,0,128,0,128,0,94,36,141,70,
|
||||
107,194,76,143,140,50,109,216,56,136,139,63,111,156,31,218,
|
||||
139,127,112,111,5,254,135,60,116,52,0,0,128,0,128,0,
|
||||
92,237,138,30,122,85,75,113,137,51,120,146,55,133,136,57,
|
||||
121,39,31,91,136,14,123,110,5,246,132,117,123,118,0,0,
|
||||
128,0,128,0,91,246,135,172,131,111,74,141,134,231,131,84,
|
||||
54,186,133,222,130,234,30,202,133,72,130,209,6,11,130,149,
|
||||
129,136,0,0,128,0,128,0,91,71,134,25,143,189,74,30,
|
||||
133,105,142,218,54,108,132,29,141,96,30,192,131,24,140,170,
|
||||
6,8,129,66,132,20,0,0,128,0,128,0,77,84,167,52,
|
||||
81,238,60,225,164,229,86,29,41,102,163,178,89,171,15,187,
|
||||
165,245,91,30,0,0,143,192,102,232,0,0,128,0,128,0,
|
||||
76,0,163,132,92,179,59,195,161,83,95,199,40,139,159,206,
|
||||
98,84,15,179,160,234,99,35,0,0,141,58,110,94,0,0,
|
||||
128,0,128,0,75,38,159,158,103,107,58,198,157,140,105,113,
|
||||
39,202,155,249,107,4,15,139,156,80,107,83,0,0,138,237,
|
||||
113,76,0,0,128,0,128,0,74,77,156,103,114,86,58,10,
|
||||
154,119,115,117,39,52,152,188,116,26,15,133,152,85,116,52,
|
||||
0,33,136,220,120,138,0,0,128,0,128,0,73,149,153,242,
|
||||
125,109,57,132,152,31,125,200,38,211,150,60,125,178,15,95,
|
||||
149,64,125,240,0,63,135,71,127,146,0,0,128,0,128,0,
|
||||
73,42,152,77,136,216,57,58,150,125,136,168,38,173,148,107,
|
||||
136,30,15,114,147,1,134,175,0,80,134,33,128,54,0,0,
|
||||
128,0,128,0,158,251,83,213,77,213,134,82,88,228,84,162,
|
||||
107,209,93,194,91,44,78,135,98,47,97,81,44,208,100,17,
|
||||
102,124,1,123,125,128,107,25,155,163,75,156,94,40,131,186,
|
||||
81,193,98,171,105,163,87,113,102,252,76,186,92,94,107,9,
|
||||
43,127,94,109,110,93,1,148,125,85,114,218,152,136,68,110,
|
||||
110,104,128,251,75,123,112,169,103,104,81,210,114,214,74,252,
|
||||
87,33,116,232,42,89,89,132,118,188,1,168,125,50,122,87,
|
||||
149,187,62,95,127,39,126,199,70,68,127,37,101,151,77,45,
|
||||
126,223,73,179,82,194,126,247,41,128,85,129,127,2,1,184,
|
||||
125,23,128,57,147,155,57,144,141,195,125,55,66,42,139,246,
|
||||
100,109,73,147,138,142,72,188,79,81,137,33,40,239,82,91,
|
||||
136,147,1,196,125,4,129,50,146,51,54,15,157,180,124,41,
|
||||
63,34,153,134,99,178,70,225,149,233,72,51,76,186,147,48,
|
||||
40,130,79,242,145,93,1,205,124,245,129,56,140,172,95,13,
|
||||
78,0,118,82,98,194,84,136,93,217,102,97,90,197,66,68,
|
||||
105,148,96,126,32,220,108,22,100,131,0,0,128,0,112,38,
|
||||
137,166,87,69,92,206,116,43,92,3,97,107,92,39,96,73,
|
||||
101,193,64,246,99,194,105,173,32,26,102,123,108,69,0,0,
|
||||
128,0,119,103,134,217,80,99,107,214,113,151,85,234,110,117,
|
||||
90,18,90,193,112,228,63,85,94,121,115,18,31,23,97,180,
|
||||
116,108,0,0,128,0,125,112,132,131,74,171,122,184,111,150,
|
||||
80,207,123,118,88,87,86,26,124,13,62,35,89,237,124,145,
|
||||
30,107,94,103,125,47,0,0,128,0,127,202,130,209,70,47,
|
||||
137,129,110,40,76,204,136,111,87,33,82,108,135,54,61,36,
|
||||
86,56,134,85,29,248,92,10,133,252,0,0,128,0,128,0,
|
||||
129,180,66,231,151,227,109,43,73,215,149,17,86,72,79,164,
|
||||
146,42,60,121,83,93,144,56,29,122,90,173,141,217,0,0,
|
||||
128,0,128,0,122,59,107,13,78,9,101,239,109,128,84,51,
|
||||
79,94,111,248,90,17,53,66,114,34,95,58,20,89,117,114,
|
||||
98,63,0,0,128,0,118,48,119,113,99,183,91,125,99,224,
|
||||
103,9,96,10,77,191,105,251,100,71,52,13,108,44,103,232,
|
||||
19,212,112,104,105,245,0,0,128,0,124,88,117,9,93,44,
|
||||
105,29,97,175,97,41,107,247,76,39,100,134,110,150,50,241,
|
||||
102,174,112,192,19,113,108,243,114,23,0,0,128,0,128,0,
|
||||
114,243,87,180,118,223,95,234,92,47,120,23,74,129,95,218,
|
||||
121,16,49,195,97,217,121,223,18,225,106,136,122,228,0,0,
|
||||
128,0,128,0,113,120,83,101,132,147,94,155,88,59,132,58,
|
||||
73,87,92,22,131,141,48,207,93,197,131,35,18,148,104,170,
|
||||
130,227,0,0,128,0,128,0,112,124,80,47,145,214,93,175,
|
||||
85,72,144,47,72,123,89,48,142,34,48,28,90,139,141,35,
|
||||
18,32,103,124,136,248,0,0,128,0,128,0,103,70,120,84,
|
||||
77,117,84,232,121,161,83,63,64,11,123,28,88,172,38,210,
|
||||
124,209,92,243,8,233,127,70,96,200,0,0,128,0,123,34,
|
||||
100,213,113,135,89,167,83,25,115,126,94,24,62,167,117,48,
|
||||
98,36,37,231,118,126,101,44,8,193,123,161,104,123,0,0,
|
||||
128,0,127,24,98,194,107,80,102,30,81,34,109,203,105,23,
|
||||
61,29,111,188,107,190,36,205,112,158,109,148,8,119,120,180,
|
||||
112,173,0,0,128,0,128,0,96,242,102,12,114,156,79,130,
|
||||
104,236,116,47,59,191,107,0,117,116,36,18,107,82,118,75,
|
||||
8,91,118,101,120,166,0,0,128,0,128,0,95,146,97,206,
|
||||
130,67,78,97,101,12,129,141,58,188,103,46,129,182,35,42,
|
||||
103,31,127,144,8,40,116,175,127,220,0,0,128,0,128,0,
|
||||
94,161,94,147,139,177,77,129,98,16,138,232,57,241,100,48,
|
||||
137,174,34,137,99,241,137,147,7,229,115,133,132,115,0,0,
|
||||
128,0,128,0,84,37,135,119,75,195,67,155,135,178,81,48,
|
||||
48,13,136,148,86,4,22,132,139,57,88,202,1,153,133,28,
|
||||
97,193,0,0,128,0,126,220,82,13,129,47,86,229,65,224,
|
||||
129,244,91,44,46,166,130,201,94,217,21,210,132,77,96,184,
|
||||
1,163,129,218,105,124,0,0,128,0,128,0,80,85,123,60,
|
||||
98,71,64,40,124,97,101,75,45,71,125,64,103,204,20,248,
|
||||
126,25,104,210,1,154,127,79,110,152,0,0,128,0,128,0,
|
||||
78,197,118,17,114,119,62,180,119,146,116,238,44,4,120,106,
|
||||
118,37,20,83,121,5,113,106,1,147,125,213,117,185,0,0,
|
||||
128,0,128,0,77,131,113,206,121,100,61,140,115,179,122,30,
|
||||
43,13,116,126,122,121,19,183,117,62,122,187,1,164,125,57,
|
||||
126,172,0,0,128,0,128,0,76,158,110,125,133,67,60,216,
|
||||
112,196,133,20,42,153,113,118,132,123,19,130,114,86,132,73,
|
||||
1,142,125,96,129,13,0,0,128,0,128,0,64,153,153,69,
|
||||
72,171,49,169,152,158,77,168,30,160,153,228,81,115,6,90,
|
||||
154,60,83,247,0,0,130,209,102,37,0,0,128,0,128,0,
|
||||
62,163,147,140,82,227,47,151,147,139,86,215,28,182,148,160,
|
||||
89,168,5,183,147,71,91,203,0,0,128,103,109,199,0,0,
|
||||
128,0,128,0,61,68,141,206,93,80,46,3,142,29,96,44,
|
||||
27,97,143,2,98,7,5,78,141,29,99,223,0,0,128,0,
|
||||
117,60,0,0,128,0,128,0,59,244,136,146,104,3,44,191,
|
||||
137,80,105,212,26,96,137,238,106,205,5,45,136,30,108,152,
|
||||
0,0,128,0,123,80,0,0,128,0,128,0,58,216,132,48,
|
||||
114,233,43,191,133,110,115,203,25,174,133,218,116,14,4,250,
|
||||
132,101,118,30,0,0,128,0,127,34,0,0,128,0,128,0,
|
||||
58,13,128,170,126,39,42,253,130,99,126,61,25,57,130,182,
|
||||
126,10,4,241,129,178,126,213,0,0,128,0,128,0,0,0,
|
||||
128,0,128,0,0,0,255,255,0,0,255,255,0,0,255,255
|
||||
};
|
||||
@@ -27,7 +27,7 @@ bool // O - `true` on sucess, `false` on EOF
|
||||
_pdfioFileConsume(pdfio_file_t *pdf, // I - PDF file
|
||||
size_t bytes) // I - Bytes to consume
|
||||
{
|
||||
PDFIO_DEBUG("_pdfioFileConsume(pdf=%p, bytes=%u)\n", (void *)pdf, (unsigned)bytes);
|
||||
PDFIO_DEBUG("_pdfioFileConsume(pdf=%p, bytes=%u)\n", pdf, (unsigned)bytes);
|
||||
|
||||
if ((size_t)(pdf->bufend - pdf->bufptr) > bytes)
|
||||
pdf->bufptr += bytes;
|
||||
@@ -91,7 +91,7 @@ _pdfioFileError(pdfio_file_t *pdf, // I - PDF file
|
||||
bool // O - `true` on success, `false` on failure
|
||||
_pdfioFileFlush(pdfio_file_t *pdf) // I - PDF file
|
||||
{
|
||||
PDFIO_DEBUG("_pdfioFileFlush(pdf=%p)\n", (void *)pdf);
|
||||
PDFIO_DEBUG("_pdfioFileFlush(pdf=%p)\n", pdf);
|
||||
|
||||
if (pdf->bufptr > pdf->buffer)
|
||||
{
|
||||
@@ -142,7 +142,7 @@ _pdfioFileGets(pdfio_file_t *pdf, // I - PDF file
|
||||
*bufend = buffer + bufsize - 1; // Pointer to end of buffer
|
||||
|
||||
|
||||
PDFIO_DEBUG("_pdfioFileGets(pdf=%p, buffer=%p, bufsize=%lu, discard=%s) bufpos=%ld, buffer=%p, bufptr=%p, bufend=%p, offset=%lu\n", (void *)pdf, (void *)buffer, (unsigned long)bufsize, discard ? "true" : "false", (long)pdf->bufpos, (void *)pdf->buffer, (void *)pdf->bufptr, (void *)pdf->bufend, (unsigned long)(pdf->bufpos + (pdf->bufptr - pdf->buffer)));
|
||||
PDFIO_DEBUG("_pdfioFileGets(pdf=%p, buffer=%p, bufsize=%lu, discard=%s) bufpos=%ld, buffer=%p, bufptr=%p, bufend=%p, offset=%lu\n", pdf, buffer, (unsigned long)bufsize, discard ? "true" : "false", (long)pdf->bufpos, pdf->buffer, pdf->bufptr, pdf->bufend, (unsigned long)(pdf->bufpos + (pdf->bufptr - pdf->buffer)));
|
||||
|
||||
while (!eol)
|
||||
{
|
||||
@@ -359,7 +359,7 @@ _pdfioFileSeek(pdfio_file_t *pdf, // I - PDF file
|
||||
off_t offset, // I - Offset
|
||||
int whence) // I - Offset base
|
||||
{
|
||||
PDFIO_DEBUG("_pdfioFileSeek(pdf=%p, offset=%ld, whence=%d) pdf->bufpos=%lu\n", (void *)pdf, (long)offset, whence, (unsigned long)(pdf ? pdf->bufpos : 0));
|
||||
PDFIO_DEBUG("_pdfioFileSeek(pdf=%p, offset=%ld, whence=%d) pdf->bufpos=%lu\n", pdf, (long)offset, whence, (unsigned long)(pdf ? pdf->bufpos : 0));
|
||||
|
||||
// Adjust offset for relative seeks...
|
||||
if (whence == SEEK_CUR)
|
||||
@@ -376,7 +376,7 @@ _pdfioFileSeek(pdfio_file_t *pdf, // I - PDF file
|
||||
// Yes, seek within existing buffer...
|
||||
pdf->bufptr = pdf->buffer + (offset - pdf->bufpos);
|
||||
PDFIO_DEBUG("_pdfioFileSeek: Seek within buffer, bufpos=%ld.\n", (long)pdf->bufpos);
|
||||
PDFIO_DEBUG("_pdfioFileSeek: buffer=%p, bufptr=%p(<%02X%02X...>), bufend=%p\n", (void *)pdf->buffer, (void *)pdf->bufptr, pdf->bufptr[0] & 255, pdf->bufptr[1] & 255, (void *)pdf->bufend);
|
||||
PDFIO_DEBUG("_pdfioFileSeek: buffer=%p, bufptr=%p(<%02X%02X...>), bufend=%p\n", pdf->buffer, pdf->bufptr, pdf->bufptr[0] & 255, pdf->bufptr[1] & 255, pdf->bufend);
|
||||
return (offset);
|
||||
}
|
||||
|
||||
@@ -411,7 +411,7 @@ _pdfioFileSeek(pdfio_file_t *pdf, // I - PDF file
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("_pdfioFileSeek: Reset bufpos=%ld, offset=%lu.\n", (long)pdf->bufpos, (unsigned long)offset);
|
||||
PDFIO_DEBUG("_pdfioFileSeek: buffer=%p, bufptr=%p, bufend=%p\n", (void *)pdf->buffer, (void *)pdf->bufptr, (void *)pdf->bufend);
|
||||
PDFIO_DEBUG("_pdfioFileSeek: buffer=%p, bufptr=%p, bufend=%p\n", pdf->buffer, pdf->bufptr, pdf->bufend);
|
||||
|
||||
pdf->bufpos = offset;
|
||||
|
||||
|
||||
2029
pdfio-content.c
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// Public content header file for PDFio.
|
||||
//
|
||||
// Copyright © 2021-2025 by Michael R Sweet.
|
||||
// Copyright © 2021-2023 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -23,8 +23,7 @@ typedef enum pdfio_cs_e // Standard color spaces
|
||||
{
|
||||
PDFIO_CS_ADOBE, // AdobeRGB 1998
|
||||
PDFIO_CS_P3_D65, // Display P3
|
||||
PDFIO_CS_SRGB, // sRGB
|
||||
PDFIO_CS_CGATS001 // CGATS001 (CMYK)
|
||||
PDFIO_CS_SRGB // sRGB
|
||||
} pdfio_cs_t;
|
||||
|
||||
typedef enum pdfio_linecap_e // Line capping modes
|
||||
@@ -69,10 +68,8 @@ extern pdfio_array_t *pdfioArrayCreateColorFromPrimaries(pdfio_file_t *pdf, size
|
||||
extern pdfio_array_t *pdfioArrayCreateColorFromStandard(pdfio_file_t *pdf, size_t num_colors, pdfio_cs_t cs);
|
||||
|
||||
// PDF content drawing functions...
|
||||
extern bool pdfioContentBeginMarked(pdfio_stream_t *st, const char *tag, pdfio_dict_t *dict) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentClip(pdfio_stream_t *st, bool even_odd) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentDrawImage(pdfio_stream_t *st, const char *name, double x, double y, double w, double h) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentEndMarked(pdfio_stream_t *st) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentFill(pdfio_stream_t *st, bool even_odd) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentFillAndStroke(pdfio_stream_t *st, bool even_odd) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentMatrixConcat(pdfio_stream_t *st, pdfio_matrix_t m) _PDFIO_PUBLIC;
|
||||
@@ -130,9 +127,7 @@ extern bool pdfioContentTextShowf(pdfio_stream_t *st, bool unicode, const char
|
||||
extern bool pdfioContentTextShowJustified(pdfio_stream_t *st, bool unicode, size_t num_fragments, const double *offsets, const char * const *fragments) _PDFIO_PUBLIC;
|
||||
|
||||
// Resource helpers...
|
||||
extern void pdfioFileAddOutputIntent(pdfio_file_t *pdf, const char *subtype, const char *condition, const char *cond_id, const char *reg_name, const char *info, pdfio_obj_t *profile) _PDFIO_PUBLIC;
|
||||
extern pdfio_obj_t *pdfioFileCreateFontObjFromBase(pdfio_file_t *pdf, const char *name) _PDFIO_PUBLIC;
|
||||
extern pdfio_obj_t *pdfioFileCreateFontObjFromData(pdfio_file_t *pdf, const void *data, size_t datasize, bool unicode) _PDFIO_PUBLIC;
|
||||
extern pdfio_obj_t *pdfioFileCreateFontObjFromFile(pdfio_file_t *pdf, const char *filename, bool unicode) _PDFIO_PUBLIC;
|
||||
extern pdfio_obj_t *pdfioFileCreateICCObjFromData(pdfio_file_t *pdf, const unsigned char *data, size_t datalen, size_t num_colors) _PDFIO_PUBLIC;
|
||||
extern pdfio_obj_t *pdfioFileCreateICCObjFromFile(pdfio_file_t *pdf, const char *filename, size_t num_colors) _PDFIO_PUBLIC;
|
||||
|
||||
277
pdfio-crypto.c
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// Cryptographic support functions for PDFio.
|
||||
//
|
||||
// Copyright © 2021-2026 by Michael R Sweet.
|
||||
// Copyright © 2021-2025 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -96,14 +96,12 @@ static uint8_t pdf_passpad[32] = // Padding for passwords
|
||||
// Local functions...
|
||||
//
|
||||
|
||||
static void decrypt_ou_key(pdfio_encryption_t encryption, const uint8_t *file_key, size_t file_keylen, uint8_t ou_key[32]);
|
||||
static void encrypt_ou_key(pdfio_encryption_t encryption, const uint8_t *file_key, size_t file_keylen, uint8_t ou_key[32]);
|
||||
static void make_file_key(pdfio_encryption_t encryption, size_t file_keylen, pdfio_permission_t permissions, const unsigned char *file_id, size_t file_idlen, const uint8_t *user_pad, const uint8_t *owner_key, bool encrypt_metadata, uint8_t file_key[16]);
|
||||
static void make_owner_key(pdfio_encryption_t encryption, size_t file_keylen, const uint8_t *owner_pad, const uint8_t *user_pad, uint8_t owner_key[32]);
|
||||
static void make_password_key(pdfio_encryption_t encryption, size_t file_keylen, const uint8_t *pad, uint8_t *key);
|
||||
static void decrypt_user_key(pdfio_encryption_t encryption, const uint8_t *file_key, uint8_t user_key[32]);
|
||||
static void encrypt_user_key(pdfio_encryption_t encryption, const uint8_t *file_key, uint8_t user_key[32]);
|
||||
static void make_file_key(pdfio_encryption_t encryption, pdfio_permission_t permissions, const unsigned char *file_id, size_t file_idlen, const uint8_t *user_pad, const uint8_t *owner_key, bool encrypt_metadata, uint8_t file_key[16]);
|
||||
static void make_owner_key(pdfio_encryption_t encryption, const uint8_t *owner_pad, const uint8_t *user_pad, uint8_t owner_key[32]);
|
||||
static void make_user_key(const unsigned char *file_id, size_t file_idlen, uint8_t user_key[32]);
|
||||
static void pad_password(const char *password, uint8_t pad[32]);
|
||||
static bool test_password(pdfio_encryption_t encryption, size_t file_keylen, pdfio_permission_t permisions,const unsigned char *file_id, size_t file_idlen, const uint8_t *user_pad, const uint8_t *user_key, const uint8_t *owner_key, bool encrypt_metadata, uint8_t file_key[16]);
|
||||
|
||||
|
||||
//
|
||||
@@ -141,7 +139,6 @@ _pdfioCryptoLock(
|
||||
case PDFIO_ENCRYPTION_AES_128 :
|
||||
// Create the 128-bit encryption keys...
|
||||
pad_password(user_password, user_pad);
|
||||
pdf->file_keylen = 16;
|
||||
|
||||
if (!owner_password && user_password && *user_password)
|
||||
{
|
||||
@@ -155,17 +152,18 @@ _pdfioCryptoLock(
|
||||
}
|
||||
|
||||
// Compute the owner key...
|
||||
make_owner_key(encryption, pdf->file_keylen, owner_pad, user_pad, pdf->owner_key);
|
||||
make_owner_key(encryption, owner_pad, user_pad, pdf->owner_key);
|
||||
pdf->owner_keylen = 32;
|
||||
|
||||
// Generate the encryption key
|
||||
file_id = pdfioArrayGetBinary(pdf->id_array, 0, &file_idlen);
|
||||
|
||||
make_file_key(encryption, pdf->file_keylen, permissions, file_id, file_idlen, user_pad, pdf->owner_key, pdf->encrypt_metadata, pdf->file_key);
|
||||
make_file_key(encryption, permissions, file_id, file_idlen, user_pad, pdf->owner_key, pdf->encrypt_metadata, pdf->file_key);
|
||||
pdf->file_keylen = 16;
|
||||
|
||||
// Generate the user key...
|
||||
make_user_key(file_id, file_idlen, pdf->user_key);
|
||||
encrypt_ou_key(encryption, pdf->file_key, pdf->file_keylen, pdf->user_key);
|
||||
encrypt_user_key(encryption, pdf->file_key, pdf->user_key);
|
||||
pdf->user_keylen = 32;
|
||||
|
||||
// Save everything in the dictionary...
|
||||
@@ -216,9 +214,8 @@ _pdfioCryptoLock(
|
||||
|
||||
pdfioObjClose(pdf->encrypt_obj);
|
||||
|
||||
pdf->encrypt_dict = dict;
|
||||
pdf->encryption = encryption;
|
||||
pdf->permissions = permissions;
|
||||
pdf->encryption = encryption;
|
||||
pdf->permissions = permissions;
|
||||
|
||||
return (true);
|
||||
}
|
||||
@@ -414,7 +411,7 @@ _pdfioCryptoMakeReader(
|
||||
uint8_t digest[16]; // MD5 digest value
|
||||
|
||||
|
||||
PDFIO_DEBUG("_pdfioCryptoMakeReader(pdf=%p, obj=%p(%d), ctx=%p, iv=%p, ivlen=%p(%d))\n", (void *)pdf, (void *)obj, (int)obj->number, (void *)ctx, (void *)iv, (void *)ivlen, (int)*ivlen);
|
||||
PDFIO_DEBUG("_pdfioCryptoMakeReader(pdf=%p, obj=%p(%d), ctx=%p, iv=%p, ivlen=%p(%d))\n", pdf, obj, (int)obj->number, ctx, iv, ivlen, (int)*ivlen);
|
||||
|
||||
// Range check input...
|
||||
if (!pdf)
|
||||
@@ -457,10 +454,6 @@ _pdfioCryptoMakeReader(
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
__attribute__((fallthrough));
|
||||
#endif // __APPLE__
|
||||
|
||||
case PDFIO_ENCRYPTION_RC4_128 :
|
||||
// Copy the key data for the MD5 hash.
|
||||
memcpy(data, pdf->file_key, 16);
|
||||
@@ -511,7 +504,7 @@ _pdfioCryptoMakeWriter(
|
||||
uint8_t digest[16]; /* MD5 digest value */
|
||||
|
||||
|
||||
PDFIO_DEBUG("_pdfioCryptoMakeWriter(pdf=%p, obj=%p(%d), ctx=%p, iv=%p, ivlen=%p(%d))\n", (void *)pdf, (void *)obj, (int)obj->number, (void *)ctx, (void *)iv, (void *)ivlen, (int)*ivlen);
|
||||
PDFIO_DEBUG("_pdfioCryptoMakeWriter(pdf=%p, obj=%p(%d), ctx=%p, iv=%p, ivlen=%p(%d))\n", pdf, obj, (int)obj->number, ctx, iv, ivlen, (int)*ivlen);
|
||||
|
||||
// Range check input...
|
||||
if (!pdf)
|
||||
@@ -573,6 +566,7 @@ _pdfioCryptoUnlock(
|
||||
{
|
||||
int tries; // Number of tries
|
||||
const char *password = NULL; // Password to try
|
||||
pdfio_dict_t *encrypt_dict; // Encrypt objection dictionary
|
||||
int version, // Version value
|
||||
revision, // Revision value
|
||||
length; // Key length value
|
||||
@@ -592,14 +586,20 @@ _pdfioCryptoUnlock(
|
||||
_pdfio_value_t *value; // Encrypt dictionary value, if any
|
||||
|
||||
|
||||
// See if we support the type of encryption specified by the Encrypt
|
||||
// See if we support the type of encryption specified by the Encrypt object
|
||||
// dictionary...
|
||||
handler = pdfioDictGetName(pdf->encrypt_dict, "Filter");
|
||||
version = (int)pdfioDictGetNumber(pdf->encrypt_dict, "V");
|
||||
revision = (int)pdfioDictGetNumber(pdf->encrypt_dict, "R");
|
||||
length = (int)pdfioDictGetNumber(pdf->encrypt_dict, "Length");
|
||||
if ((encrypt_dict = pdfioObjGetDict(pdf->encrypt_obj)) == NULL)
|
||||
{
|
||||
_pdfioFileError(pdf, "Unable to get encryption dictionary.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if ((value = _pdfioDictGetValue(pdf->encrypt_dict, "EncryptMetadata")) != NULL && value->type == PDFIO_VALTYPE_BOOLEAN)
|
||||
handler = pdfioDictGetName(encrypt_dict, "Filter");
|
||||
version = (int)pdfioDictGetNumber(encrypt_dict, "V");
|
||||
revision = (int)pdfioDictGetNumber(encrypt_dict, "R");
|
||||
length = (int)pdfioDictGetNumber(encrypt_dict, "Length");
|
||||
|
||||
if ((value = _pdfioDictGetValue(encrypt_dict, "EncryptMetadata")) != NULL && value->type == PDFIO_VALTYPE_BOOLEAN)
|
||||
pdf->encrypt_metadata = value->value.boolean;
|
||||
else
|
||||
pdf->encrypt_metadata = true;
|
||||
@@ -618,9 +618,9 @@ _pdfioCryptoUnlock(
|
||||
pdfio_dict_t *filter; // Crypt Filter
|
||||
const char *cfm; // Crypt filter method
|
||||
|
||||
stream_filter = pdfioDictGetName(pdf->encrypt_dict, "StmF");
|
||||
string_filter = pdfioDictGetName(pdf->encrypt_dict, "StrF");
|
||||
cf_dict = pdfioDictGetDict(pdf->encrypt_dict, "CF");
|
||||
stream_filter = pdfioDictGetName(encrypt_dict, "StmF");
|
||||
string_filter = pdfioDictGetName(encrypt_dict, "StrF");
|
||||
cf_dict = pdfioDictGetDict(encrypt_dict, "CF");
|
||||
|
||||
if (!cf_dict)
|
||||
{
|
||||
@@ -693,16 +693,11 @@ _pdfioCryptoUnlock(
|
||||
_pdfioFileError(pdf, "Unsupported encryption V%d R%d.", version, revision);
|
||||
return (false);
|
||||
}
|
||||
else if (length < 40 || length > 128)
|
||||
{
|
||||
_pdfioFileError(pdf, "Unsupported key length %d.", length);
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Grab the remaining values we need to unlock the PDF...
|
||||
pdf->file_keylen = (size_t)(length / 8);
|
||||
|
||||
p = pdfioDictGetNumber(pdf->encrypt_dict, "P");
|
||||
p = pdfioDictGetNumber(encrypt_dict, "P");
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: P=%.0f\n", p);
|
||||
if (p < 0x7fffffff) // Handle integers > 2^31-1
|
||||
pdf->permissions = (pdfio_permission_t)p;
|
||||
@@ -710,8 +705,8 @@ _pdfioCryptoUnlock(
|
||||
pdf->permissions = (pdfio_permission_t)(p - 4294967296.0);
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: permissions=%d\n", pdf->permissions);
|
||||
|
||||
owner_key = pdfioDictGetBinary(pdf->encrypt_dict, "O", &owner_keylen);
|
||||
user_key = pdfioDictGetBinary(pdf->encrypt_dict, "U", &user_keylen);
|
||||
owner_key = pdfioDictGetBinary(encrypt_dict, "O", &owner_keylen);
|
||||
user_key = pdfioDictGetBinary(encrypt_dict, "U", &user_keylen);
|
||||
|
||||
if (!owner_key)
|
||||
{
|
||||
@@ -740,7 +735,7 @@ _pdfioCryptoUnlock(
|
||||
return (false);
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: user_key[%d]=<%02X%02X%02X%02X...%02X%02X%02X%02X>\n", (int)user_keylen, user_key[0], user_key[1], user_key[2], user_key[3], user_key[28], user_key[29], user_key[30], user_key[31]);
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: user_key[%d]=%02X%02X%02X%02X...%02X%02X%02X%02X\n", (int)user_keylen, user_key[0], user_key[1], user_key[2], user_key[3], user_key[28], user_key[29], user_key[30], user_key[31]);
|
||||
|
||||
memcpy(pdf->user_key, user_key, user_keylen);
|
||||
pdf->user_keylen = user_keylen;
|
||||
@@ -751,9 +746,6 @@ _pdfioCryptoUnlock(
|
||||
return (false);
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: P=%d\n", pdf->permissions);
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: file_id(%d)=<%02X%02X%02X%02X...%02X%02X%02X%02X>\n", (int)file_idlen, file_id[0], file_id[1], file_id[2], file_id[3], file_id[12], file_id[13], file_id[14], file_id[15]);
|
||||
|
||||
// Generate a base hash from known values...
|
||||
_pdfioCryptoMD5Init(&md5);
|
||||
_pdfioCryptoMD5Append(&md5, pdf_passpad, 32);
|
||||
@@ -765,34 +757,56 @@ _pdfioCryptoUnlock(
|
||||
{
|
||||
if (pdf->encryption <= PDFIO_ENCRYPTION_AES_128)
|
||||
{
|
||||
// RC4 and AES-128 encryption...
|
||||
uint8_t pad[32], // Padded password
|
||||
padkey[16], // Password key
|
||||
file_key[16]; // File key
|
||||
file_key[16], // File key
|
||||
user_pad[32], // Padded user password
|
||||
own_user_key[32], // Calculated user key
|
||||
pdf_user_key[32]; // Decrypted user key
|
||||
|
||||
// Pad the supplied password, if any...
|
||||
pad_password(password, pad);
|
||||
|
||||
// Test the user password...
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: Trying <%02X%02X%02X%02X...%02X%02X%02X%02X>\n", pad[0], pad[1], pad[2], pad[3], pad[28], pad[29], pad[30], pad[31]);
|
||||
// Generate keys to see if things match...
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: Trying %02X%02X%02X%02X...%02X%02X%02X%02X\n", pad[0], pad[1], pad[2], pad[3], pad[28], pad[29], pad[30], pad[31]);
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: P=%d\n", pdf->permissions);
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: Fid(%d)=%02X%02X%02X%02X...%02X%02X%02X%02X\n", (int)file_idlen, file_id[0], file_id[1], file_id[2], file_id[3], file_id[12], file_id[13], file_id[14], file_id[15]);
|
||||
|
||||
if (test_password(pdf->encryption, pdf->file_keylen, pdf->permissions, file_id, file_idlen, pad, pdf->user_key, pdf->owner_key, pdf->encrypt_metadata, file_key))
|
||||
make_owner_key(pdf->encryption, pad, pdf->owner_key, user_pad);
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: Upad=%02X%02X%02X%02X...%02X%02X%02X%02X\n", user_pad[0], user_pad[1], user_pad[2], user_pad[3], user_pad[28], user_pad[29], user_pad[30], user_pad[31]);
|
||||
|
||||
make_file_key(pdf->encryption, pdf->permissions, file_id, file_idlen, user_pad, pdf->owner_key, pdf->encrypt_metadata, file_key);
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: Fown=%02X%02X%02X%02X...%02X%02X%02X%02X\n", file_key[0], file_key[1], file_key[2], file_key[3], file_key[12], file_key[13], file_key[14], file_key[15]);
|
||||
|
||||
make_user_key(file_id, file_idlen, own_user_key);
|
||||
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: U=%02X%02X%02X%02X...%02X%02X%02X%02X\n", pdf->user_key[0], pdf->user_key[1], pdf->user_key[2], pdf->user_key[3], pdf->user_key[28], pdf->user_key[29], pdf->user_key[30], pdf->user_key[31]);
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: Uown=%02X%02X%02X%02X...%02X%02X%02X%02X\n", own_user_key[0], own_user_key[1], own_user_key[2], own_user_key[3], own_user_key[28], own_user_key[29], own_user_key[30], own_user_key[31]);
|
||||
|
||||
if (!memcmp(own_user_key, pdf->user_key, sizeof(own_user_key)))
|
||||
{
|
||||
memcpy(pdf->file_key, file_key, pdf->file_keylen);
|
||||
// Matches!
|
||||
memcpy(pdf->file_key, file_key, sizeof(pdf->file_key));
|
||||
memcpy(pdf->password, pad, sizeof(pdf->password));
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
// Test the owner password...
|
||||
make_password_key(pdf->encryption, pdf->file_keylen, pad, padkey);
|
||||
// Not the owner password, try the user password...
|
||||
make_file_key(pdf->encryption, pdf->permissions, file_id, file_idlen, pad, pdf->owner_key, pdf->encrypt_metadata, file_key);
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: Fuse=%02X%02X%02X%02X...%02X%02X%02X%02X\n", file_key[0], file_key[1], file_key[2], file_key[3], file_key[12], file_key[13], file_key[14], file_key[15]);
|
||||
|
||||
memcpy(pad, pdf->owner_key, sizeof(pad));
|
||||
decrypt_ou_key(pdf->encryption, padkey, pdf->file_keylen, pad);
|
||||
make_user_key(file_id, file_idlen, own_user_key);
|
||||
|
||||
if (test_password(pdf->encryption, pdf->file_keylen, pdf->permissions, file_id, file_idlen, pad, pdf->user_key, pdf->owner_key, pdf->encrypt_metadata, file_key))
|
||||
memcpy(pdf_user_key, pdf->user_key, sizeof(pdf_user_key));
|
||||
decrypt_user_key(pdf->encryption, file_key, pdf_user_key);
|
||||
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: Uuse=%02X%02X%02X%02X...%02X%02X%02X%02X\n", user_key[0], user_key[1], user_key[2], user_key[3], user_key[28], user_key[29], user_key[30], user_key[31]);
|
||||
PDFIO_DEBUG("_pdfioCryptoUnlock: Updf=%02X%02X%02X%02X...%02X%02X%02X%02X\n", pdf_user_key[0], pdf_user_key[1], pdf_user_key[2], pdf_user_key[3], pdf_user_key[28], pdf_user_key[29], pdf_user_key[30], pdf_user_key[31]);
|
||||
|
||||
if (!memcmp(pad, pdf_user_key, 32) || !memcmp(own_user_key, pdf_user_key, 16))
|
||||
{
|
||||
memcpy(pdf->file_key, file_key, pdf->file_keylen);
|
||||
// Matches!
|
||||
memcpy(pdf->file_key, file_key, sizeof(pdf->file_key));
|
||||
memcpy(pdf->password, pad, sizeof(pdf->password));
|
||||
|
||||
return (true);
|
||||
@@ -820,15 +834,14 @@ _pdfioCryptoUnlock(
|
||||
|
||||
|
||||
//
|
||||
// 'decrypt_ou_key()' - Decrypt the user key.
|
||||
// 'decrypt_user_key()' - Decrypt the user key.
|
||||
//
|
||||
|
||||
static void
|
||||
decrypt_ou_key(
|
||||
decrypt_user_key(
|
||||
pdfio_encryption_t encryption, // I - Type of encryption
|
||||
const uint8_t *file_key, // I - File encryption key
|
||||
size_t file_keylen, // I - Length of file encryption key
|
||||
uint8_t ou_key[32]) // IO - Owner/User key
|
||||
uint8_t user_key[32]) // IO - User key
|
||||
{
|
||||
size_t i, j; // Looping vars
|
||||
_pdfio_rc4_t rc4; // RC4 encryption context
|
||||
@@ -838,38 +851,38 @@ decrypt_ou_key(
|
||||
{
|
||||
// Encrypt the result once...
|
||||
_pdfioCryptoRC4Init(&rc4, file_key, 5);
|
||||
_pdfioCryptoRC4Crypt(&rc4, ou_key, ou_key, 32);
|
||||
_pdfioCryptoRC4Crypt(&rc4, user_key, user_key, 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Encrypt the result 20 times...
|
||||
uint8_t key[16]; // Current encryption key
|
||||
|
||||
for (i = 20; i > 0;)
|
||||
for (i = 19; i > 0; i --)
|
||||
{
|
||||
// XOR each byte in the key with the loop counter...
|
||||
i --;
|
||||
|
||||
for (j = 0; j < file_keylen; j ++)
|
||||
for (j = 0; j < 16; j ++)
|
||||
key[j] = (uint8_t)(file_key[j] ^ i);
|
||||
|
||||
_pdfioCryptoRC4Init(&rc4, key, file_keylen);
|
||||
_pdfioCryptoRC4Crypt(&rc4, ou_key, ou_key, 32);
|
||||
_pdfioCryptoRC4Init(&rc4, key, 16);
|
||||
_pdfioCryptoRC4Crypt(&rc4, user_key, user_key, 32);
|
||||
}
|
||||
|
||||
_pdfioCryptoRC4Init(&rc4, file_key, 16);
|
||||
_pdfioCryptoRC4Crypt(&rc4, user_key, user_key, 32);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'encrypt_ou_key()' - Encrypt the owner/user key.
|
||||
// 'encrypt_user_key()' - Encrypt the user key.
|
||||
//
|
||||
|
||||
static void
|
||||
encrypt_ou_key(
|
||||
encrypt_user_key(
|
||||
pdfio_encryption_t encryption, // I - Type of encryption
|
||||
const uint8_t *file_key, // I - File encryption key
|
||||
size_t file_keylen, // I - Length of file encryption key
|
||||
uint8_t ou_key[32]) // IO - Owner/User key
|
||||
uint8_t user_key[32]) // IO - User key
|
||||
{
|
||||
size_t i, j; // Looping vars
|
||||
_pdfio_rc4_t rc4; // RC4 encryption context
|
||||
@@ -879,7 +892,7 @@ encrypt_ou_key(
|
||||
{
|
||||
// Encrypt the result once...
|
||||
_pdfioCryptoRC4Init(&rc4, file_key, 5);
|
||||
_pdfioCryptoRC4Crypt(&rc4, ou_key, ou_key, 32);
|
||||
_pdfioCryptoRC4Crypt(&rc4, user_key, user_key, 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -889,11 +902,11 @@ encrypt_ou_key(
|
||||
for (i = 0; i < 20; i ++)
|
||||
{
|
||||
// XOR each byte in the key with the loop counter...
|
||||
for (j = 0; j < file_keylen; j ++)
|
||||
for (j = 0; j < 16; j ++)
|
||||
key[j] = (uint8_t)(file_key[j] ^ i);
|
||||
|
||||
_pdfioCryptoRC4Init(&rc4, key, file_keylen);
|
||||
_pdfioCryptoRC4Crypt(&rc4, ou_key, ou_key, 32);
|
||||
_pdfioCryptoRC4Init(&rc4, key, 16);
|
||||
_pdfioCryptoRC4Crypt(&rc4, user_key, user_key, 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -906,7 +919,6 @@ encrypt_ou_key(
|
||||
static void
|
||||
make_file_key(
|
||||
pdfio_encryption_t encryption, // I - Type of encryption
|
||||
size_t file_keylen, // I - Encryption key length
|
||||
pdfio_permission_t permissions, // I - File permissions
|
||||
const unsigned char *file_id, // I - File ID value
|
||||
size_t file_idlen, // I - Length of file ID
|
||||
@@ -952,14 +964,14 @@ make_file_key(
|
||||
for (i = 0; i < 50; i ++)
|
||||
{
|
||||
_pdfioCryptoMD5Init(&md5);
|
||||
_pdfioCryptoMD5Append(&md5, digest, file_keylen);
|
||||
_pdfioCryptoMD5Append(&md5, digest, 16);
|
||||
_pdfioCryptoMD5Finish(&md5, digest);
|
||||
}
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("make_file_key: file_key[16]=<%02X%02X%02X%02X...%02X%02X%02X%02X>\n", digest[0], digest[1], digest[2], digest[3], digest[12], digest[13], digest[14], digest[15]);
|
||||
|
||||
memcpy(file_key, digest, file_keylen);
|
||||
memcpy(file_key, digest, 16);
|
||||
}
|
||||
|
||||
|
||||
@@ -970,57 +982,57 @@ make_file_key(
|
||||
static void
|
||||
make_owner_key(
|
||||
pdfio_encryption_t encryption, // I - Type of encryption
|
||||
size_t file_keylen, // I - Length of encryption key
|
||||
const uint8_t *owner_pad, // I - Padded owner password
|
||||
const uint8_t *user_pad, // I - Padded user password
|
||||
uint8_t owner_key[32]) // O - Owner key value
|
||||
{
|
||||
uint8_t key[16]; // Base encryption key
|
||||
size_t i, j; // Looping vars
|
||||
_pdfio_md5_t md5; // MD5 context
|
||||
uint8_t digest[16]; // 128-bit MD5 digest
|
||||
_pdfio_rc4_t rc4; // RC4 encryption context
|
||||
|
||||
|
||||
// Hash the owner password...
|
||||
make_password_key(encryption, file_keylen, owner_pad, key);
|
||||
|
||||
// Copy and encrypt the padded user password...
|
||||
memcpy(owner_key, user_pad, 32);
|
||||
decrypt_ou_key(encryption, key, file_keylen, owner_key);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'make_password_key()' - Make a password key.
|
||||
//
|
||||
|
||||
static void
|
||||
make_password_key(
|
||||
pdfio_encryption_t encryption, // I - Type of encryption
|
||||
size_t file_keylen, // I - Length of encryption key
|
||||
const uint8_t *pad, // I - Padded password
|
||||
uint8_t *key) // O - Key data
|
||||
{
|
||||
size_t i; // Looping var
|
||||
_pdfio_md5_t md5; // MD5 context
|
||||
uint8_t digest[16]; // 128-bit MD5 digest
|
||||
|
||||
|
||||
// Hash the padded password...
|
||||
_pdfioCryptoMD5Init(&md5);
|
||||
_pdfioCryptoMD5Append(&md5, pad, 32);
|
||||
_pdfioCryptoMD5Append(&md5, owner_pad, 32);
|
||||
_pdfioCryptoMD5Finish(&md5, digest);
|
||||
|
||||
if (encryption != PDFIO_ENCRYPTION_RC4_40)
|
||||
{
|
||||
// Hash the hash another 50 times...
|
||||
for (i = 0; i < 50; i ++)
|
||||
{
|
||||
_pdfioCryptoMD5Init(&md5);
|
||||
_pdfioCryptoMD5Append(&md5, digest, file_keylen);
|
||||
_pdfioCryptoMD5Append(&md5, digest, 16);
|
||||
_pdfioCryptoMD5Finish(&md5, digest);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the key portion of the hashed password to the key...
|
||||
memcpy(key, digest, file_keylen);
|
||||
// Copy and encrypt the padded user password...
|
||||
memcpy(owner_key, user_pad, 32);
|
||||
|
||||
if (encryption == PDFIO_ENCRYPTION_RC4_40)
|
||||
{
|
||||
// Encrypt once...
|
||||
_pdfioCryptoRC4Init(&rc4, digest, 5);
|
||||
_pdfioCryptoRC4Crypt(&rc4, owner_key, owner_key, 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Encrypt 20 times...
|
||||
uint8_t encrypt_key[16]; // RC4 encryption key
|
||||
|
||||
for (i = 20; i > 0;)
|
||||
{
|
||||
// XOR each byte in the digest with the loop counter to make a key...
|
||||
i --;
|
||||
|
||||
for (j = 0; j < sizeof(encrypt_key); j ++)
|
||||
encrypt_key[j] = (uint8_t)(digest[j] ^ i);
|
||||
|
||||
_pdfioCryptoRC4Init(&rc4, encrypt_key, sizeof(encrypt_key));
|
||||
_pdfioCryptoRC4Crypt(&rc4, owner_key, owner_key, 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1075,52 +1087,3 @@ pad_password(const char *password, // I - Password string or `NULL`
|
||||
if (len < 32)
|
||||
memcpy(pad + len, pdf_passpad, 32 - len);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'test_password()' - Test a user password...
|
||||
//
|
||||
|
||||
static bool // O - `true` if password is correct, `false` otherwise
|
||||
test_password(
|
||||
pdfio_encryption_t encryption, // I - Type of encryption
|
||||
size_t file_keylen, // I - Length of encryption key
|
||||
pdfio_permission_t permissions, // I - File permissions
|
||||
const unsigned char *file_id, // I - File ID value
|
||||
size_t file_idlen, // I - Length of file ID
|
||||
const uint8_t *user_pad, // I - Padded user password
|
||||
const uint8_t *user_key, // I - User key
|
||||
const uint8_t *owner_key, // I - Owner key
|
||||
bool encrypt_metadata,
|
||||
// I - Encrypt metadata?
|
||||
uint8_t file_key[16]) // O - Encryption key
|
||||
{
|
||||
uint8_t pdf_user_key[32]; // Decrypted user key
|
||||
|
||||
|
||||
// Make the file key...
|
||||
make_file_key(encryption, file_keylen, permissions, file_id, file_idlen, user_pad, owner_key, encrypt_metadata, file_key);
|
||||
|
||||
// Decrypt the user key using the file key...
|
||||
memcpy(pdf_user_key, user_key, sizeof(pdf_user_key));
|
||||
decrypt_ou_key(encryption, file_key, file_keylen, pdf_user_key);
|
||||
PDFIO_DEBUG("test_password: pdf_user_key[32]=<%02X%02X%02X%02X...%02X%02X%02X%02X>\n", pdf_user_key[0], pdf_user_key[1], pdf_user_key[2], pdf_user_key[3], pdf_user_key[28], pdf_user_key[29], pdf_user_key[30], pdf_user_key[31]);
|
||||
|
||||
if (encryption == PDFIO_ENCRYPTION_RC4_40 && !memcmp(pdf_user_key, pdf_passpad, 32))
|
||||
{
|
||||
// 40-bit encryption just compares the eecrypted user key matches...
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 128-bit encryption needs to match the calculated user key...
|
||||
uint8_t own_user_key[32]; // Calculated user key
|
||||
|
||||
// Calculate what the user key should be...
|
||||
make_user_key(file_id, file_idlen, own_user_key);
|
||||
PDFIO_DEBUG("test_password: own_user_key[32]=<%02X%02X%02X%02X...%02X%02X%02X%02X>\n", own_user_key[0], own_user_key[1], own_user_key[2], own_user_key[3], own_user_key[28], own_user_key[29], own_user_key[30], own_user_key[31]);
|
||||
|
||||
// Return whether they match...
|
||||
return (!memcmp(pdf_user_key, own_user_key, 16));
|
||||
}
|
||||
}
|
||||
|
||||
69
pdfio-dict.c
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// PDF dictionary functions for PDFio.
|
||||
//
|
||||
// Copyright © 2021-2026 by Michael R Sweet.
|
||||
// Copyright © 2021-2025 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -32,7 +32,7 @@ pdfioDictClear(pdfio_dict_t *dict, // I - Dictionary
|
||||
pkey; // Search key
|
||||
|
||||
|
||||
PDFIO_DEBUG("pdfioDictClear(dict=%p, key=\"%s\")\n", (void *)dict, key);
|
||||
PDFIO_DEBUG("pdfioDictClear(dict=%p, key=\"%s\")\n", dict, key);
|
||||
|
||||
if (!dict || !key)
|
||||
return (false);
|
||||
@@ -77,11 +77,7 @@ pdfioDictCopy(pdfio_file_t *pdf, // I - PDF file
|
||||
_pdfio_value_t v; // Current destination value
|
||||
|
||||
|
||||
PDFIO_DEBUG("pdfioDictCopy(pdf=%p, dict=%p(%p))\n", (void *)pdf, (void *)dict, dict ? (void *)dict->pdf : NULL);
|
||||
|
||||
// Range check input...
|
||||
if (!pdf || !dict)
|
||||
return (NULL);
|
||||
PDFIO_DEBUG("pdfioDictCopy(pdf=%p, dict=%p(%p))\n", pdf, dict, dict ? dict->pdf : NULL);
|
||||
|
||||
// Create the new dictionary...
|
||||
if ((ndict = pdfioDictCreate(pdf)) == NULL)
|
||||
@@ -96,8 +92,6 @@ pdfioDictCopy(pdfio_file_t *pdf, // I - PDF file
|
||||
// Copy and add each of the source dictionary's key/value pairs...
|
||||
for (i = dict->num_pairs, p = dict->pairs; i > 0; i --, p ++)
|
||||
{
|
||||
PDFIO_DEBUG("pdfioDictCopy: key=\"%s\", value.type=%d\n", p->key, p->value.type);
|
||||
|
||||
if (!strcmp(p->key, "Length") && p->value.type == PDFIO_VALTYPE_INDIRECT && dict->pdf != pdf)
|
||||
{
|
||||
// Don't use indirect stream lengths for copied objects...
|
||||
@@ -108,28 +102,15 @@ pdfioDictCopy(pdfio_file_t *pdf, // I - PDF file
|
||||
if (lenobj)
|
||||
{
|
||||
if (lenobj->value.type == PDFIO_VALTYPE_NONE)
|
||||
{
|
||||
if (!_pdfioObjLoad(lenobj))
|
||||
{
|
||||
PDFIO_DEBUG("pdfioDictCopy: Unable to copy value of \"%s\", returning NULL.\n", p->key);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
_pdfioObjLoad(lenobj);
|
||||
|
||||
v.value.number = lenobj->value.value.number;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.value.number = 0.0;
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("pdfioDictCopy: Length is %.0f.\n", v.value.number);
|
||||
}
|
||||
else if (!_pdfioValueCopy(pdf, &v, dict->pdf, &p->value))
|
||||
{
|
||||
PDFIO_DEBUG("pdfioDictCopy: Unable to copy value of \"%s\", returning NULL.\n", p->key);
|
||||
return (NULL); // Let pdfioFileClose do the cleanup...
|
||||
}
|
||||
|
||||
if (_pdfioStringIsAllocated(dict->pdf, p->key))
|
||||
key = pdfioStringCreate(pdf, p->key);
|
||||
@@ -483,12 +464,8 @@ pdfioDictGetString(pdfio_dict_t *dict, // I - Dictionary
|
||||
_pdfio_value_t *value = _pdfioDictGetValue(dict, key);
|
||||
|
||||
|
||||
PDFIO_DEBUG("pdfioDictGetString(dict=%p, key=\"%s\")\n", (void *)dict, key);
|
||||
PDFIO_DEBUG("pdfioDictGetString: value=%p(type=%d)\n", (void *)value, value ? value->type : 0);
|
||||
|
||||
if (value && value->type == PDFIO_VALTYPE_STRING)
|
||||
{
|
||||
PDFIO_DEBUG("pdfioDictGetString: Returning \"%s\".\n", value->value.string);
|
||||
return (value->value.string);
|
||||
}
|
||||
else if (value && value->type == PDFIO_VALTYPE_BINARY && value->value.binary.datalen < 4096)
|
||||
@@ -499,8 +476,6 @@ pdfioDictGetString(pdfio_dict_t *dict, // I - Dictionary
|
||||
if (!(value->value.binary.datalen & 1) && (!memcmp(value->value.binary.data, "\376\377", 2) || !memcmp(value->value.binary.data, "\377\376", 2)))
|
||||
{
|
||||
// Copy UTF-16...
|
||||
PDFIO_DEBUG("pdfioDictGetString: Converting UTF-16 to UTF-8 string.\n");
|
||||
|
||||
_pdfio_utf16cpy(temp, value->value.binary.data, value->value.binary.datalen, sizeof(temp));
|
||||
}
|
||||
else
|
||||
@@ -514,13 +489,10 @@ pdfioDictGetString(pdfio_dict_t *dict, // I - Dictionary
|
||||
value->type = PDFIO_VALTYPE_STRING;
|
||||
value->value.string = pdfioStringCreate(dict->pdf, temp);
|
||||
|
||||
PDFIO_DEBUG("pdfioDictGetString: Returning \"%s\".\n", value->value.string);
|
||||
|
||||
return (value->value.string);
|
||||
}
|
||||
else
|
||||
{
|
||||
PDFIO_DEBUG("pdfioDictGetString: Returning NULL.\n");
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
@@ -553,7 +525,7 @@ _pdfioDictGetValue(pdfio_dict_t *dict, // I - Dictionary
|
||||
*match; // Matching key pair
|
||||
|
||||
|
||||
PDFIO_DEBUG("_pdfioDictGetValue(dict=%p, key=\"%s\")\n", (void *)dict, key);
|
||||
PDFIO_DEBUG("_pdfioDictGetValue(dict=%p, key=\"%s\")\n", dict, key);
|
||||
|
||||
if (!dict || !dict->num_pairs || !key)
|
||||
{
|
||||
@@ -638,7 +610,7 @@ _pdfioDictRead(pdfio_file_t *pdf, // I - PDF file
|
||||
_pdfio_value_t value; // Dictionary value
|
||||
|
||||
|
||||
PDFIO_DEBUG("_pdfioDictRead(pdf=%p, obj=%p, tb=%p, depth=%lu)\n", (void *)pdf, (void *)obj, (void *)tb, (unsigned long)depth);
|
||||
PDFIO_DEBUG("_pdfioDictRead(pdf=%p, obj=%p, tb=%p, depth=%lu)\n", pdf, obj, tb, (unsigned long)depth);
|
||||
|
||||
// Create a dictionary and start reading...
|
||||
if ((dict = pdfioDictCreate(pdf)) == NULL)
|
||||
@@ -669,7 +641,8 @@ _pdfioDictRead(pdfio_file_t *pdf, // I - PDF file
|
||||
}
|
||||
else if (_pdfioDictGetValue(dict, key + 1))
|
||||
{
|
||||
// Issue 118: Discard duplicate key/value pairs...
|
||||
// Issue 118: Discard duplicate key/value pairs, in the future this will
|
||||
// be a warning message...
|
||||
_pdfioValueDelete(&value);
|
||||
if (_pdfioFileError(pdf, "WARNING: Discarding value for duplicate dictionary key '%s'.", key + 1))
|
||||
continue;
|
||||
@@ -1011,7 +984,7 @@ _pdfioDictSetValue(
|
||||
_pdfio_pair_t *pair; // Current pair
|
||||
|
||||
|
||||
PDFIO_DEBUG("_pdfioDictSetValue(dict=%p, key=\"%s\", value=%p)\n", (void *)dict, key, (void *)value);
|
||||
PDFIO_DEBUG("_pdfioDictSetValue(dict=%p, key=\"%s\", value=%p)\n", dict, key, (void *)value);
|
||||
|
||||
// See if the key is already set...
|
||||
if (dict->num_pairs > 0)
|
||||
@@ -1073,13 +1046,11 @@ _pdfioDictSetValue(
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
_pdfioDictWrite(
|
||||
_pdfio_printf_t cb, // I - Printf callback function
|
||||
void *cbdata, // I - Printf callback data
|
||||
pdfio_obj_t *obj, // I - Object, if any
|
||||
pdfio_dict_t *dict, // I - Dictionary
|
||||
off_t *length) // I - Offset to length value
|
||||
_pdfioDictWrite(pdfio_dict_t *dict, // I - Dictionary
|
||||
pdfio_obj_t *obj, // I - Object, if any
|
||||
off_t *length) // I - Offset to length value
|
||||
{
|
||||
pdfio_file_t *pdf = dict->pdf; // PDF file
|
||||
size_t i; // Looping var
|
||||
_pdfio_pair_t *pair; // Current key/value pair
|
||||
|
||||
@@ -1088,30 +1059,28 @@ _pdfioDictWrite(
|
||||
*length = 0;
|
||||
|
||||
// Dictionaries are bounded by "<<" and ">>"...
|
||||
if (!(cb)(cbdata, "<<"))
|
||||
if (!_pdfioFilePuts(pdf, "<<"))
|
||||
return (false);
|
||||
|
||||
// Write all of the key/value pairs...
|
||||
for (i = dict->num_pairs, pair = dict->pairs; i > 0; i --, pair ++)
|
||||
{
|
||||
if (!(cb)(cbdata, "%N", pair->key))
|
||||
if (!_pdfioFilePrintf(pdf, "%N", pair->key))
|
||||
return (false);
|
||||
|
||||
if (length && !strcmp(pair->key, "Length") && pair->value.type == PDFIO_VALTYPE_NUMBER && pair->value.value.number <= 0.0)
|
||||
{
|
||||
// Writing an object dictionary with an undefined length
|
||||
*length = _pdfioFileTell(dict->pdf) + 1;
|
||||
if (!(cb)(cbdata, " 9999999999"))
|
||||
*length = _pdfioFileTell(pdf) + 1;
|
||||
if (!_pdfioFilePuts(pdf, " 9999999999"))
|
||||
return (false);
|
||||
}
|
||||
else if (!_pdfioValueWrite(cb, cbdata, obj, &pair->value, NULL))
|
||||
{
|
||||
else if (!_pdfioValueWrite(pdf, obj, &pair->value, NULL))
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
// Close it up...
|
||||
return ((cb)(cbdata, ">>"));
|
||||
return (_pdfioFilePuts(pdf, ">>"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
849
pdfio-file.c
338
pdfio-lzw.c
@@ -1,338 +0,0 @@
|
||||
//
|
||||
// LZW decoding functions for PDFio.
|
||||
//
|
||||
// This code is used to support (legacy) PDF object streams using the LZWDecode
|
||||
// filter as well as when embedding (legacy) GIF images. None of this is public
|
||||
// API and we only support reading (decoding) since FlateDecode is superior in
|
||||
// every way.
|
||||
//
|
||||
// Copyright © 2026 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
//
|
||||
|
||||
#include "pdfio-private.h"
|
||||
|
||||
|
||||
//
|
||||
// Local functions...
|
||||
//
|
||||
|
||||
static void lzw_clear(_pdfio_lzw_t *lzw);
|
||||
static int lzw_get_code(_pdfio_lzw_t *lzw);
|
||||
|
||||
|
||||
//
|
||||
// '_pdfioLZWCreate()' - Create a LZW decompressor.
|
||||
//
|
||||
|
||||
_pdfio_lzw_t * // O - LZW state
|
||||
_pdfioLZWCreate(int code_size, // I - Data code size in bits (typically 8 for PDF, 2-8 for GIF)
|
||||
int early, // I - Number of early codes
|
||||
bool reversed) // I - Reversed (GIF) LZW bit encoding?
|
||||
{
|
||||
_pdfio_lzw_t *lzw; // LZW state
|
||||
|
||||
|
||||
if ((lzw = (_pdfio_lzw_t *)calloc(1, sizeof(_pdfio_lzw_t))) != NULL)
|
||||
{
|
||||
lzw->def_code_size = (uint8_t)(code_size + 1);
|
||||
lzw->clear_code = (uint16_t)(1 << code_size);
|
||||
lzw->eod_code = lzw->clear_code + 1;
|
||||
lzw->early = (uint8_t)early;
|
||||
lzw->reversed = reversed;
|
||||
|
||||
lzw_clear(lzw);
|
||||
}
|
||||
|
||||
return (lzw);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// '_pdfioLZWDelete()' - Delete a LZW decompressor.
|
||||
//
|
||||
|
||||
void
|
||||
_pdfioLZWDelete(_pdfio_lzw_t *lzw) // I - LZW state
|
||||
{
|
||||
free(lzw);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// '_pdfioLZWInflate()' - Decompress pending input data.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on error
|
||||
_pdfioLZWInflate(_pdfio_lzw_t *lzw) // I - LZW state
|
||||
{
|
||||
int cur_code, // Current code
|
||||
in_code; // Input code
|
||||
|
||||
|
||||
// Stop if we already saw the "end of data" code...
|
||||
if (lzw->saw_eod)
|
||||
{
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: EOD, returning false.\n");
|
||||
lzw->error = "End of data.";
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Copy pending compressed data to the output buffer...
|
||||
while (lzw->stptr > lzw->stack && lzw->avail_out > 0)
|
||||
{
|
||||
*(lzw->next_out++) = (uint8_t)*(--lzw->stptr);
|
||||
lzw->avail_out --;
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: Unrolled value %d, stptr=%p(%ld), avail_out=%u\n", *(lzw->stptr), (void *)lzw->stptr, lzw->stptr - lzw->stack, (unsigned)lzw->avail_out);
|
||||
}
|
||||
|
||||
// Loop as long as we have room in the output buffer and data in the input
|
||||
// buffer...
|
||||
while (lzw->avail_out > 0)
|
||||
{
|
||||
if ((in_code = lzw_get_code(lzw)) < 0)
|
||||
{
|
||||
// Out of data, stop now...
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: Out of data.\n");
|
||||
break;
|
||||
}
|
||||
else if (in_code == lzw->clear_code)
|
||||
{
|
||||
// Clear the compression tables and reset...
|
||||
lzw_clear(lzw);
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: Clear.\n");
|
||||
continue;
|
||||
}
|
||||
else if (in_code == lzw->eod_code)
|
||||
{
|
||||
// End of data...
|
||||
lzw->saw_eod = true;
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: EOD.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// If we get this far we have something to write to the output buffer and/or
|
||||
// stack...
|
||||
if (lzw->first_code == 0xffff)
|
||||
{
|
||||
// First code...
|
||||
lzw->first_code = lzw->old_code = (uint16_t)in_code;
|
||||
*(lzw->next_out++) = (uint8_t)in_code;
|
||||
lzw->avail_out --;
|
||||
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: first_code=%d.\n", in_code);
|
||||
continue;
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: in_code=%d, old_code=%d.\n", in_code, lzw->old_code);
|
||||
|
||||
cur_code = in_code;
|
||||
|
||||
if (cur_code >= lzw->next_code)
|
||||
{
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: New cur_code=%d, next_code=%d\n", cur_code, lzw->next_code);
|
||||
*(lzw->stptr++) = lzw->first_code;
|
||||
cur_code = lzw->old_code;
|
||||
}
|
||||
|
||||
while (cur_code >= lzw->clear_code)
|
||||
{
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: cur_code=%d (%d,%d)\n", cur_code, lzw->table[cur_code].prefix_code, lzw->table[cur_code].suffix);
|
||||
|
||||
// Protect against overflow/loops...
|
||||
if (lzw->stptr >= (lzw->stack + sizeof(lzw->stack) / sizeof(lzw->stack[0])))
|
||||
{
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: Stack overflow, returning false.\n");
|
||||
lzw->error = "Output overflow.";
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Add this character to the output stack and move to the next character
|
||||
// in the sequence...
|
||||
*(lzw->stptr++) = lzw->table[cur_code].suffix;
|
||||
|
||||
if (cur_code == lzw->table[cur_code].prefix_code)
|
||||
{
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: Table loop on code %d, returning false.\n", cur_code);
|
||||
lzw->error = "Table loop detected.";
|
||||
return (false);
|
||||
}
|
||||
|
||||
cur_code = lzw->table[cur_code].prefix_code;
|
||||
}
|
||||
|
||||
if (lzw->stptr >= (lzw->stack + sizeof(lzw->stack) / sizeof(lzw->stack[0])))
|
||||
{
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: Stack overflow, returning false.\n");
|
||||
lzw->error = "Output overflow.";
|
||||
return (false);
|
||||
}
|
||||
|
||||
*(lzw->stptr++) = lzw->first_code = lzw->table[cur_code].suffix;
|
||||
|
||||
if ((cur_code = lzw->next_code) < 4096)
|
||||
{
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: Adding code %d (%d,%d), next_size_code=%d\n", cur_code, lzw->old_code, lzw->first_code, lzw->next_size_code);
|
||||
|
||||
lzw->table[cur_code].prefix_code = lzw->old_code;
|
||||
lzw->table[cur_code].suffix = lzw->first_code;
|
||||
lzw->next_code ++;
|
||||
|
||||
if (lzw->next_code >= lzw->next_size_code && lzw->cur_code_size < 12)
|
||||
{
|
||||
lzw->cur_code_size ++;
|
||||
lzw->next_size_code = (uint16_t)((1 << lzw->cur_code_size) - lzw->early);
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: Increased code size to %u, next_size_code=%u\n", lzw->cur_code_size, lzw->next_size_code);
|
||||
}
|
||||
}
|
||||
|
||||
lzw->old_code = (uint16_t)in_code;
|
||||
|
||||
while (lzw->stptr > lzw->stack && lzw->avail_out > 0)
|
||||
{
|
||||
*(lzw->next_out++) = (uint8_t)*(--lzw->stptr);
|
||||
lzw->avail_out --;
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: Unrolled value %d, stptr=%p(%ld), avail_out=%u\n", *(lzw->stptr), (void *)lzw->stptr, lzw->stptr - lzw->stack, (unsigned)lzw->avail_out);
|
||||
}
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("_pdfioLZWInflate: Returning true, avail_in=%u, avail_out=%u.\n", (unsigned)lzw->avail_in, (unsigned)lzw->avail_out);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'lzw_clear()' - Clear the compression table.
|
||||
//
|
||||
|
||||
static void
|
||||
lzw_clear(_pdfio_lzw_t *lzw) // I - LZW state
|
||||
{
|
||||
uint16_t i; // Looping var
|
||||
|
||||
|
||||
lzw->cur_code_size = lzw->def_code_size;
|
||||
lzw->next_code = lzw->clear_code + 2;
|
||||
lzw->next_size_code = (uint16_t)((1 << lzw->cur_code_size) - lzw->early);
|
||||
lzw->first_code = 0xffff;
|
||||
lzw->old_code = 0xffff;
|
||||
|
||||
memset(lzw->table, 0, sizeof(lzw->table));
|
||||
|
||||
for (i = 0; i < lzw->clear_code; i ++)
|
||||
lzw->table[i].suffix = i;
|
||||
|
||||
lzw->stptr = lzw->stack;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'lzw_get_code()' - Get a code from the input buffer.
|
||||
//
|
||||
|
||||
static int // O - Code or -1 if there is not enough data available
|
||||
lzw_get_code(_pdfio_lzw_t *lzw) // I - LZW state
|
||||
{
|
||||
uint16_t code, // Code
|
||||
in_bit; // Bit offset in buffer
|
||||
uint8_t bits, // Bits in current byte
|
||||
boff, // Bit offset in current byte
|
||||
byte, // Current byte
|
||||
remaining; // Remaining bits for code
|
||||
static uint8_t mask[8] = // Value mask
|
||||
{
|
||||
0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f
|
||||
};
|
||||
static uint8_t rbits[8] = // Right-to-left bit masks
|
||||
{
|
||||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
|
||||
};
|
||||
|
||||
|
||||
// Fill input bytes as needed...
|
||||
if ((lzw->in_bit + lzw->cur_code_size) > lzw->in_bits)
|
||||
{
|
||||
uint16_t in_used = lzw->in_bits / 8,
|
||||
// Number of input bytes
|
||||
in_offset = lzw->in_bit / 8,
|
||||
// Offset to current input
|
||||
in_add; // Number of bytes to "read"
|
||||
|
||||
|
||||
if (lzw->avail_in == 0)
|
||||
{
|
||||
// No more data
|
||||
PDFIO_DEBUG("lzw_get_code: No data, returning -1.\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (in_offset > 0)
|
||||
{
|
||||
// Make room in the input buffer
|
||||
memmove(lzw->in_bytes, lzw->in_bytes + in_offset, in_used - in_offset);
|
||||
in_used -= in_offset;
|
||||
lzw->in_bit &= 7;
|
||||
}
|
||||
|
||||
if ((in_add = sizeof(lzw->in_bytes) - in_used) > lzw->avail_in)
|
||||
in_add = (uint16_t)lzw->avail_in;
|
||||
|
||||
memcpy(lzw->in_bytes + in_used, lzw->next_in, in_add);
|
||||
lzw->next_in += in_add;
|
||||
lzw->avail_in -= in_add;
|
||||
lzw->in_bits = 8 * (in_used + in_add);
|
||||
|
||||
if ((lzw->in_bit + lzw->cur_code_size) > lzw->in_bits)
|
||||
{
|
||||
// Not enough data
|
||||
PDFIO_DEBUG("lzw_get_code: Not enough data, returning -1.\n");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("lzw_get_code: in_bit=%u, in_bits=%u, in_bytes=<...%02X%02X%02X...>, cur_code_size=%u\n", lzw->in_bit, lzw->in_bits, lzw->in_bytes[lzw->in_bit / 8], lzw->in_bytes[lzw->in_bit / 8 + 1], lzw->in_bytes[lzw->in_bit / 8 + 2], lzw->cur_code_size);
|
||||
|
||||
// Now extract the code from the buffer...
|
||||
if (lzw->reversed)
|
||||
{
|
||||
// Insane GIF-style right-to-left bit encoding...
|
||||
for (code = 0, in_bit = lzw->in_bit + lzw->cur_code_size - 1, remaining = lzw->cur_code_size; remaining > 0; in_bit --, remaining --)
|
||||
{
|
||||
code = (uint16_t)((code << 1) | ((lzw->in_bytes[in_bit / 8] & rbits[in_bit & 7]) != 0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TIFF/PDF-style left-to-right bit encoding...
|
||||
for (code = 0, in_bit = lzw->in_bit, remaining = lzw->cur_code_size; remaining > 0; in_bit += bits, remaining -= bits)
|
||||
{
|
||||
// See how many bits we can extract from the current byte...
|
||||
boff = (in_bit & 7);
|
||||
byte = lzw->in_bytes[in_bit / 8];
|
||||
bits = 8 - boff;
|
||||
if (bits > remaining)
|
||||
bits = remaining;
|
||||
|
||||
// Get those bits
|
||||
if (bits == 8) // Full byte from buffer
|
||||
code = (uint16_t)((code << 8) | byte);
|
||||
else // Partial byte from buffer
|
||||
code = (uint16_t)((code << bits) | ((byte >> (8 - bits - boff)) & mask[bits]));
|
||||
}
|
||||
}
|
||||
|
||||
// Update the position in the input buffer and return the code...
|
||||
lzw->in_bit += lzw->cur_code_size;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (code >= 0x20 && code < 0x7f)
|
||||
PDFIO_DEBUG("lzw_get_code: Returning %u('%c').\n", code, code);
|
||||
else
|
||||
PDFIO_DEBUG("lzw_get_code: Returning %u.\n", code);
|
||||
#endif // DEBUG
|
||||
|
||||
return ((int)code);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// PDF object functions for PDFio.
|
||||
//
|
||||
// Copyright © 2021-2026 by Michael R Sweet.
|
||||
// Copyright © 2021-2025 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -32,43 +32,8 @@ pdfioObjClose(pdfio_obj_t *obj) // I - Object
|
||||
}
|
||||
|
||||
// Write what remains for the object...
|
||||
if (!obj->offset && !obj->objstm_data)
|
||||
if (!obj->offset)
|
||||
{
|
||||
// Are we using object streams and is this object eligible?
|
||||
if (obj->pdf->objstm_dict && !obj->pdf->objstm_obj && obj != obj->pdf->encrypt_obj && obj->pdf->num_objstm < 0x10000 && (obj->value.type == PDFIO_VALTYPE_ARRAY || obj->value.type == PDFIO_VALTYPE_DICT))
|
||||
{
|
||||
// Add this to the object stream...
|
||||
_pdfio_strbuf_t *bptr; // String buffer
|
||||
|
||||
if (!_pdfioStringAllocBuffer(obj->pdf, &bptr))
|
||||
goto regular_obj;
|
||||
|
||||
if (!_pdfioValueWrite((_pdfio_printf_t)_pdfioStringPrintf, bptr, /*obj*/NULL, &(obj->value), /*length*/NULL))
|
||||
{
|
||||
_pdfioStringFreeBuffer(obj->pdf, bptr->buffer);
|
||||
goto regular_obj;
|
||||
}
|
||||
|
||||
_pdfioStringPrintf(bptr, "\n");
|
||||
|
||||
if ((obj->objstm_data = pdfioStringCreate(obj->pdf, bptr->buffer)) == NULL)
|
||||
{
|
||||
_pdfioStringFreeBuffer(obj->pdf, bptr->buffer);
|
||||
goto regular_obj;
|
||||
}
|
||||
|
||||
// If we got this far then we have the value string and can assign an
|
||||
// object number, which is all that is required for now...
|
||||
obj->objstm_datalen = (size_t)(bptr->bufptr - bptr->buffer);
|
||||
obj->objstm_number = obj->pdf->num_objstm;
|
||||
obj->pdf->num_objstm ++;
|
||||
|
||||
_pdfioStringFreeBuffer(obj->pdf, bptr->buffer);
|
||||
return (true);
|
||||
}
|
||||
|
||||
regular_obj:
|
||||
|
||||
// Write the object value
|
||||
if (!_pdfioObjWriteHeader(obj))
|
||||
return (false);
|
||||
@@ -104,7 +69,7 @@ pdfioObjCopy(pdfio_file_t *pdf, // I - PDF file
|
||||
ssize_t bytes; // Bytes read
|
||||
|
||||
|
||||
PDFIO_DEBUG("pdfioObjCopy(pdf=%p, srcobj=%p(%u,%p))\n", (void *)pdf, (void *)srcobj, srcobj ? (unsigned)srcobj->number : 0, srcobj ? (void *)srcobj->pdf : NULL);
|
||||
PDFIO_DEBUG("pdfioObjCopy(pdf=%p, srcobj=%p(%p))\n", pdf, srcobj, srcobj ? srcobj->pdf : NULL);
|
||||
|
||||
// Range check input
|
||||
if (!pdf || !srcobj)
|
||||
@@ -112,10 +77,7 @@ pdfioObjCopy(pdfio_file_t *pdf, // I - PDF file
|
||||
|
||||
// Load the object value if needed...
|
||||
if (srcobj->value.type == PDFIO_VALTYPE_NONE)
|
||||
{
|
||||
if (!_pdfioObjLoad(srcobj))
|
||||
return (NULL);
|
||||
}
|
||||
_pdfioObjLoad(srcobj);
|
||||
|
||||
// See if we have already mapped this object...
|
||||
if ((dstobj = _pdfioFileFindMappedObj(pdf, srcobj->pdf, srcobj->number)) != NULL)
|
||||
@@ -346,7 +308,7 @@ pdfioObjGetLength(pdfio_obj_t *obj) // I - Object
|
||||
// Try getting the length, directly or indirectly
|
||||
if ((length = (size_t)pdfioDictGetNumber(obj->value.value.dict, "Length")) > 0)
|
||||
{
|
||||
PDFIO_DEBUG("pdfioObjGetLength(obj=%p) returning %lu.\n", (void *)obj, (unsigned long)length);
|
||||
PDFIO_DEBUG("pdfioObjGetLength(obj=%p) returning %lu.\n", obj, (unsigned long)length);
|
||||
return (length);
|
||||
}
|
||||
|
||||
@@ -366,7 +328,7 @@ pdfioObjGetLength(pdfio_obj_t *obj) // I - Object
|
||||
return (0);
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("pdfioObjGetLength(obj=%p) returning %lu.\n", (void *)obj, (unsigned long)lenobj->value.value.number);
|
||||
PDFIO_DEBUG("pdfioObjGetLength(obj=%p) returning %lu.\n", obj, (unsigned long)lenobj->value.value.number);
|
||||
|
||||
return ((size_t)lenobj->value.value.number);
|
||||
}
|
||||
@@ -478,7 +440,7 @@ _pdfioObjLoad(pdfio_obj_t *obj) // I - Object
|
||||
_pdfio_token_t tb; // Token buffer/stack
|
||||
|
||||
|
||||
PDFIO_DEBUG("_pdfioObjLoad(obj=%p(%lu)), offset=%lu\n", (void *)obj, (unsigned long)obj->number, (unsigned long)obj->offset);
|
||||
PDFIO_DEBUG("_pdfioObjLoad(obj=%p(%lu)), offset=%lu\n", obj, (unsigned long)obj->number, (unsigned long)obj->offset);
|
||||
|
||||
// Seek to the start of the object and read its header...
|
||||
if (_pdfioFileSeek(obj->pdf, obj->offset, SEEK_SET) != obj->offset)
|
||||
@@ -540,7 +502,7 @@ _pdfioObjLoad(pdfio_obj_t *obj) // I - Object
|
||||
return (false);
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("_pdfioObjLoad: tb.bufptr=%p, tb.bufend=%p, tb.bufptr[0]=0x%02x, tb.bufptr[1]=0x%02x\n", (void *)tb.bufptr, (void *)tb.bufend, tb.bufptr[0], tb.bufptr[1]);
|
||||
PDFIO_DEBUG("_pdfioObjLoad: tb.bufptr=%p, tb.bufend=%p, tb.bufptr[0]=0x%02x, tb.bufptr[1]=0x%02x\n", tb.bufptr, tb.bufend, tb.bufptr[0], tb.bufptr[1]);
|
||||
|
||||
_pdfioTokenFlush(&tb);
|
||||
|
||||
@@ -582,8 +544,6 @@ pdfioObjOpenStream(pdfio_obj_t *obj, // I - Object
|
||||
pdfio_stream_t *st; // Stream
|
||||
|
||||
|
||||
PDFIO_DEBUG("pdfioObjOpenStream(obj=%p(%lu), decode=%s)\n", (void *)obj, obj ? (unsigned long)obj->number : 0, decode ? "true" : "false");
|
||||
|
||||
// Range check input...
|
||||
if (!obj)
|
||||
return (NULL);
|
||||
@@ -603,10 +563,7 @@ pdfioObjOpenStream(pdfio_obj_t *obj, // I - Object
|
||||
|
||||
// No stream if there is no dict or offset to a stream...
|
||||
if (obj->value.type != PDFIO_VALTYPE_DICT || !obj->stream_offset)
|
||||
{
|
||||
PDFIO_DEBUG("pdfioObjOpenStream: value.type=%d, stream_offset=%ld\n", obj->value.type, (long)obj->stream_offset);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
// Open the stream...
|
||||
if ((st = _pdfioStreamOpen(obj, decode)) != NULL)
|
||||
@@ -643,7 +600,7 @@ _pdfioObjWriteHeader(pdfio_obj_t *obj) // I - Object
|
||||
if (!_pdfioFilePrintf(obj->pdf, "%lu %u obj\n", (unsigned long)obj->number, obj->generation))
|
||||
return (false);
|
||||
|
||||
if (!_pdfioValueWrite((_pdfio_printf_t)_pdfioFilePrintf, obj->pdf, obj, &obj->value, &obj->length_offset))
|
||||
if (!_pdfioValueWrite(obj->pdf, obj, &obj->value, &obj->length_offset))
|
||||
return (false);
|
||||
|
||||
return (_pdfioFilePuts(obj->pdf, "\n"));
|
||||
|
||||
335
pdfio-page.c
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// PDF page functions for PDFio.
|
||||
//
|
||||
// Copyright © 2021-2026 by Michael R Sweet.
|
||||
// Copyright © 2021-2022 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -15,7 +15,6 @@
|
||||
//
|
||||
|
||||
static _pdfio_value_t *get_contents(pdfio_obj_t *page);
|
||||
static _pdfio_value_t *get_page_value(pdfio_obj_t *page, const char *key);
|
||||
|
||||
|
||||
//
|
||||
@@ -29,7 +28,7 @@ pdfioPageCopy(pdfio_file_t *pdf, // I - PDF file
|
||||
pdfio_obj_t *dstpage; // Destination page object
|
||||
|
||||
|
||||
PDFIO_DEBUG("pdfioPageCopy(pdf=%p, srcpage=%p(%p))\n", (void *)pdf, (void *)srcpage, srcpage ? (void *)srcpage->pdf : NULL);
|
||||
PDFIO_DEBUG("pdfioPageCopy(pdf=%p, srcpage=%p(%p))\n", pdf, srcpage, srcpage ? srcpage->pdf : NULL);
|
||||
|
||||
// Range check input
|
||||
if (!pdf || !srcpage || srcpage->value.type != PDFIO_VALTYPE_DICT)
|
||||
@@ -53,158 +52,6 @@ pdfioPageCopy(pdfio_file_t *pdf, // I - PDF file
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioPageGetArray()' - Get an array value from the page dictionary.
|
||||
//
|
||||
// This function looks up an array value in the page dictionary, either in the
|
||||
// specified object or one of its parents.
|
||||
//
|
||||
// @since PDFio v1.7@
|
||||
//
|
||||
|
||||
pdfio_array_t * // O - Array or `NULL` if none
|
||||
pdfioPageGetArray(pdfio_obj_t *page, // I - Page object
|
||||
const char *key) // I - Dictionary key
|
||||
{
|
||||
_pdfio_value_t *v = get_page_value(page, key);
|
||||
// Dictionary value
|
||||
|
||||
|
||||
if (v && v->type == PDFIO_VALTYPE_ARRAY)
|
||||
return (v->value.array);
|
||||
else
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioPageGetBinary()' - Get a binary value from the page dictionary.
|
||||
//
|
||||
// This function looks up a binary value in the page dictionary, either in the
|
||||
// specified object or one of its parents.
|
||||
//
|
||||
// @since PDFio v1.7@
|
||||
//
|
||||
|
||||
unsigned char * // O - Pointer to binary data or `NULL` if none
|
||||
pdfioPageGetBinary(pdfio_obj_t *page, // I - Page object
|
||||
const char *key, // I - Dictionary key
|
||||
size_t *length) // O - Length of value
|
||||
{
|
||||
_pdfio_value_t *v = get_page_value(page, key);
|
||||
// Dictionary value
|
||||
|
||||
|
||||
if (v && v->type == PDFIO_VALTYPE_BINARY)
|
||||
{
|
||||
if (length)
|
||||
*length = v->value.binary.datalen;
|
||||
|
||||
return (v->value.binary.data);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioPageGetBoolean()' - Get a boolean value from the page dictionary.
|
||||
//
|
||||
// This function looks up a boolean value in the page dictionary, either in the
|
||||
// specified object or one of its parents.
|
||||
//
|
||||
// @since PDFio v1.7@
|
||||
//
|
||||
|
||||
bool // O - Boolean value or `false` if none
|
||||
pdfioPageGetBoolean(pdfio_obj_t *page, // I - Page object
|
||||
const char *key) // I - Dictionary key
|
||||
{
|
||||
_pdfio_value_t *v = get_page_value(page, key);
|
||||
// Dictionary value
|
||||
|
||||
|
||||
if (v && v->type == PDFIO_VALTYPE_ARRAY)
|
||||
return (v->value.boolean);
|
||||
else
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioPageGetDate()' - Get a date value from the page dictionary.
|
||||
//
|
||||
// This function looks up a date value in the page dictionary, either in the
|
||||
// specified object or one of its parents.
|
||||
//
|
||||
// @since PDFio v1.7@
|
||||
//
|
||||
|
||||
time_t // O - Date/time or `0` if none
|
||||
pdfioPageGetDate(pdfio_obj_t *page, // I - Page object
|
||||
const char *key) // I - Dictionary key
|
||||
{
|
||||
_pdfio_value_t *v = get_page_value(page, key);
|
||||
// Dictionary value
|
||||
|
||||
|
||||
if (v && v->type == PDFIO_VALTYPE_DATE)
|
||||
return (v->value.date);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioPageGetDict()' - Get a dictionary value from the page dictionary.
|
||||
//
|
||||
// This function looks up a dictionary value in the page dictionary, either in
|
||||
// the specified object or one of its parents.
|
||||
//
|
||||
// @since PDFio v1.7@
|
||||
//
|
||||
|
||||
pdfio_dict_t * // O - Dictionary or `NULL` if none
|
||||
pdfioPageGetDict(pdfio_obj_t *page, // I - Page object
|
||||
const char *key) // I - Dictionary key
|
||||
{
|
||||
_pdfio_value_t *v = get_page_value(page, key);
|
||||
// Dictionary value
|
||||
|
||||
|
||||
if (v && v->type == PDFIO_VALTYPE_DICT)
|
||||
return (v->value.dict);
|
||||
else
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioPageGetName()' - Get a name value from the page dictionary.
|
||||
//
|
||||
// This function looks up a name value in the page dictionary, either in the
|
||||
// specified object or one of its parents.
|
||||
//
|
||||
// @since PDFio v1.7@
|
||||
//
|
||||
|
||||
const char * // O - Name string or `NULL` if none
|
||||
pdfioPageGetName(pdfio_obj_t *page, // I - Page object
|
||||
const char *key) // I - Dictionary key
|
||||
{
|
||||
_pdfio_value_t *v = get_page_value(page, key);
|
||||
// Dictionary value
|
||||
|
||||
|
||||
if (v && v->type == PDFIO_VALTYPE_NAME)
|
||||
return (v->value.name);
|
||||
else
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioPageGetNumStreams()' - Get the number of content streams for a page object.
|
||||
//
|
||||
@@ -226,112 +73,6 @@ pdfioPageGetNumStreams(
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioPageGetNumber()' - Get a number value from the page dictionary.
|
||||
//
|
||||
// This function looks up a number value in the page dictionary, either in the
|
||||
// specified object or one of its parents.
|
||||
//
|
||||
// @since PDFio v1.7@
|
||||
//
|
||||
|
||||
double // O - Number value or `0.0` if none
|
||||
pdfioPageGetNumber(pdfio_obj_t *page, // I - Page object
|
||||
const char *key) // I - Dictionary key
|
||||
{
|
||||
_pdfio_value_t *v = get_page_value(page, key);
|
||||
// Dictionary value
|
||||
|
||||
|
||||
if (v && v->type == PDFIO_VALTYPE_NUMBER)
|
||||
return (v->value.number);
|
||||
else
|
||||
return (0.0);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioPageGetObj()' - Get an indirect object value from the page dictionary.
|
||||
//
|
||||
// This function looks up an indirect object value in the page dictionary,
|
||||
// either in the specified object or one of its parents.
|
||||
//
|
||||
// @since PDFio v1.7@
|
||||
//
|
||||
|
||||
pdfio_obj_t * // O - Object or `NULL` if none
|
||||
pdfioPageGetObj(pdfio_obj_t *page, // I - Page object
|
||||
const char *key) // I - Dictionary key
|
||||
{
|
||||
_pdfio_value_t *v = get_page_value(page, key);
|
||||
// Dictionary value
|
||||
|
||||
|
||||
if (v && v->type == PDFIO_VALTYPE_INDIRECT)
|
||||
return (pdfioFileFindObj(page->pdf, v->value.indirect.number));
|
||||
else
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioPageGetRect()' - Get a rectangle value from the page dictionary.
|
||||
//
|
||||
// This function looks up a rectangle value in the page dictionary, either in
|
||||
// the specified object or one of its parents.
|
||||
//
|
||||
// @since PDFio v1.7@
|
||||
//
|
||||
|
||||
pdfio_rect_t * // O - Rectangle or `NULL` if none
|
||||
pdfioPageGetRect(pdfio_obj_t *page, // I - Page object
|
||||
const char *key, // I - Dictionary key
|
||||
pdfio_rect_t *rect) // O - Rectangle
|
||||
{
|
||||
_pdfio_value_t *v = get_page_value(page, key);
|
||||
// Dictionary value
|
||||
|
||||
|
||||
if (v && v->type == PDFIO_VALTYPE_ARRAY && pdfioArrayGetSize(v->value.array) == 4)
|
||||
{
|
||||
rect->x1 = pdfioArrayGetNumber(v->value.array, 0);
|
||||
rect->y1 = pdfioArrayGetNumber(v->value.array, 1);
|
||||
rect->x2 = pdfioArrayGetNumber(v->value.array, 2);
|
||||
rect->y2 = pdfioArrayGetNumber(v->value.array, 3);
|
||||
|
||||
return (rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioPageGetString()' - Get a string value from the page dictionary.
|
||||
//
|
||||
// This function looks up a string value in the page dictionary, either in the
|
||||
// specified object or one of its parents.
|
||||
//
|
||||
// @since PDFio v1.7@
|
||||
//
|
||||
|
||||
const char * // O - String value or `NULL` if none
|
||||
pdfioPageGetString(pdfio_obj_t *page, // I - Page object
|
||||
const char *key) // I - Dictionary key
|
||||
{
|
||||
_pdfio_value_t *v = get_page_value(page, key);
|
||||
// Dictionary value
|
||||
|
||||
|
||||
if (v && v->type == PDFIO_VALTYPE_STRING)
|
||||
return (v->value.string);
|
||||
else
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioPageOpenStream()' - Open a content stream for a page.
|
||||
//
|
||||
@@ -346,28 +87,14 @@ pdfioPageOpenStream(
|
||||
// Contents value
|
||||
|
||||
|
||||
PDFIO_DEBUG("pdfioPageOpenStream(page=%p(%lu), n=%lu, decode=%s)\n", (void *)page, page ? (unsigned long)page->number : 0, (unsigned long)n, decode ? "true" : "false");
|
||||
|
||||
if (!contents)
|
||||
{
|
||||
PDFIO_DEBUG("pdfioPageOpenStream: No contents.\n");
|
||||
return (NULL);
|
||||
}
|
||||
else if (contents->type == PDFIO_VALTYPE_ARRAY && n < pdfioArrayGetSize(contents->value.array))
|
||||
{
|
||||
PDFIO_DEBUG("pdfioPageOpenStream: Contents is array, opening numbered content stream.\n");
|
||||
return (pdfioObjOpenStream(pdfioArrayGetObj(contents->value.array, n), decode));
|
||||
}
|
||||
else if (n)
|
||||
{
|
||||
PDFIO_DEBUG("pdfioPageOpenStream: Numbered stream does not exist.\n");
|
||||
return (NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
PDFIO_DEBUG("pdfioPageOpenStream: Opening single content stream %d.\n", (int)contents->value.indirect.number);
|
||||
return (pdfioObjOpenStream(pdfioFileFindObj(page->pdf, contents->value.indirect.number), decode));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -378,10 +105,6 @@ pdfioPageOpenStream(
|
||||
static _pdfio_value_t * // O - Value or NULL on error
|
||||
get_contents(pdfio_obj_t *page) // I - Page object
|
||||
{
|
||||
_pdfio_value_t *contents; // Contents value
|
||||
pdfio_obj_t *obj; // Contents object
|
||||
|
||||
|
||||
// Range check input...
|
||||
if (!page)
|
||||
return (NULL);
|
||||
@@ -396,57 +119,5 @@ get_contents(pdfio_obj_t *page) // I - Page object
|
||||
if (page->value.type != PDFIO_VALTYPE_DICT)
|
||||
return (NULL);
|
||||
|
||||
if ((contents = _pdfioDictGetValue(page->value.value.dict, "Contents")) == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (contents->type == PDFIO_VALTYPE_INDIRECT)
|
||||
{
|
||||
// See if the indirect object is a stream or an array of indirect object
|
||||
// references...
|
||||
if ((obj = pdfioFileFindObj(page->pdf, contents->value.indirect.number)) != NULL)
|
||||
{
|
||||
if (obj->value.type == PDFIO_VALTYPE_NONE)
|
||||
{
|
||||
if (!_pdfioObjLoad(obj))
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (obj->value.type == PDFIO_VALTYPE_ARRAY)
|
||||
contents = &(obj->value);
|
||||
}
|
||||
}
|
||||
|
||||
return (contents);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'get_page_value()' - Get a page dictionary value, including parents.
|
||||
//
|
||||
|
||||
static _pdfio_value_t * // O - Dictionary value or `NULL` if none
|
||||
get_page_value(pdfio_obj_t *page, // I - Page object
|
||||
const char *key) // I - Dictionary key
|
||||
{
|
||||
_pdfio_value_t *v = NULL; // Dictionary value
|
||||
|
||||
|
||||
while (page != NULL)
|
||||
{
|
||||
// Load the page object as needed...
|
||||
if (page->value.type == PDFIO_VALTYPE_NONE && !_pdfioObjLoad(page))
|
||||
break;
|
||||
|
||||
// If there isn't a dictionary for the object, stop...
|
||||
if (page->value.type != PDFIO_VALTYPE_DICT)
|
||||
break;
|
||||
|
||||
// Lookup the key...
|
||||
if ((v = _pdfioDictGetValue(page->value.value.dict, key)) != NULL)
|
||||
break;
|
||||
|
||||
page = pdfioDictGetObj(page->value.value.dict, "Parent");
|
||||
}
|
||||
|
||||
return (v);
|
||||
return (_pdfioDictGetValue(page->value.value.dict, "Contents"));
|
||||
}
|
||||
|
||||
100
pdfio-private.h
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// Private header file for PDFio.
|
||||
//
|
||||
// Copyright © 2021-2026 by Michael R Sweet.
|
||||
// Copyright © 2021-2025 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -94,12 +94,10 @@
|
||||
//
|
||||
|
||||
# define PDFIO_MAX_DEPTH 32 // Maximum nesting depth for values
|
||||
# define PDFIO_MAX_STRING 131072 // Maximum length of string
|
||||
# define PDFIO_MAX_STRING 65536 // Maximum length of string
|
||||
|
||||
typedef void (*_pdfio_extfree_t)(void *p);
|
||||
typedef void (*_pdfio_extfree_t)(void *);
|
||||
// Extension data free function
|
||||
typedef bool (*_pdfio_printf_t)(void *data, const char *format, ...);
|
||||
// "printf" function
|
||||
|
||||
typedef enum _pdfio_mode_e // Read/write mode
|
||||
{
|
||||
@@ -119,21 +117,6 @@ typedef enum _pdfio_predictor_e // PNG predictor constants
|
||||
_PDFIO_PREDICTOR_PNG_AUTO = 15 // PNG "auto" predictor (currently mapped to Paeth)
|
||||
} _pdfio_predictor_t;
|
||||
|
||||
typedef enum _pdfio_profile_e // PDF profile constants
|
||||
{
|
||||
_PDFIO_PROFILE_NONE = 0, // Base PDF file
|
||||
_PDFIO_PROFILE_PCLM, // PCLm (PDF raster) file
|
||||
_PDFIO_PROFILE_PDFA_1A, // PDF/A-1a:2005
|
||||
_PDFIO_PROFILE_PDFA_1B, // PDF/A-1b:2005
|
||||
_PDFIO_PROFILE_PDFA_2A, // PDF/A-2a:2011
|
||||
_PDFIO_PROFILE_PDFA_2B, // PDF/A-2b:2011
|
||||
_PDFIO_PROFILE_PDFA_2U, // PDF/A-2u:2011
|
||||
_PDFIO_PROFILE_PDFA_3A, // PDF/A-3a:2012
|
||||
_PDFIO_PROFILE_PDFA_3B, // PDF/A-3b:2012
|
||||
_PDFIO_PROFILE_PDFA_3U, // PDF/A-3u:2012
|
||||
_PDFIO_PROFILE_PDFA_4 // PDF/A-4:2020
|
||||
} _pdfio_profile_t;
|
||||
|
||||
typedef ssize_t (*_pdfio_tconsume_cb_t)(void *data, size_t bytes);
|
||||
typedef ssize_t (*_pdfio_tpeek_cb_t)(void *data, void *buffer, size_t bytes);
|
||||
|
||||
@@ -178,7 +161,7 @@ typedef struct _pdfio_value_s // Value structure
|
||||
typedef struct _pdfio_aes_s // AES encryption state
|
||||
{
|
||||
size_t round_size; // Size of round key
|
||||
uint8_t round_key[256], // Round key
|
||||
uint8_t round_key[240], // Round key
|
||||
iv[16]; // Initialization vector
|
||||
} _pdfio_aes_t;
|
||||
|
||||
@@ -213,38 +196,6 @@ typedef union _pdfio_crypto_ctx_u // Cryptographic contexts
|
||||
} _pdfio_crypto_ctx_t;
|
||||
typedef size_t (*_pdfio_crypto_cb_t)(_pdfio_crypto_ctx_t *ctx, uint8_t *outbuffer, const uint8_t *inbuffer, size_t len);
|
||||
|
||||
typedef struct _pdfio_lzws_s // LZW string table
|
||||
{
|
||||
uint16_t prefix_code, // Prefix code
|
||||
suffix; // Suffix (character)
|
||||
} _pdfio_lzws_t;
|
||||
|
||||
typedef struct _pdfio_lzw_s // LZW state
|
||||
{
|
||||
uint8_t *next_in; // Next input byte
|
||||
size_t avail_in; // Available input bytes
|
||||
uint8_t in_bytes[256]; // Current input bytes
|
||||
uint16_t in_bit, // Current input bit
|
||||
in_bits; // Total input bits
|
||||
uint8_t *next_out; // Next output byte
|
||||
size_t avail_out; // Available output bytes
|
||||
uint8_t cur_code_size, // Current code size
|
||||
def_code_size, // Initial/default code size
|
||||
early; // Early code change offset
|
||||
bool reversed; // Reversed bit encoding?
|
||||
uint16_t clear_code, // Clear code
|
||||
eod_code, // End code
|
||||
next_code, // Next code to be used
|
||||
next_size_code, // Code where we need to increase the code size
|
||||
first_code, // First code in sequence
|
||||
old_code, // Previous code in sequence
|
||||
stack[8192], // Output stack
|
||||
*stptr; // Current stack pointer
|
||||
_pdfio_lzws_t table[4096]; // String table
|
||||
bool saw_eod; // Saw end-of-data code?
|
||||
const char *error; // Error, if any
|
||||
} _pdfio_lzw_t;
|
||||
|
||||
struct _pdfio_array_s
|
||||
{
|
||||
pdfio_file_t *pdf; // PDF file
|
||||
@@ -277,11 +228,9 @@ typedef struct _pdfio_objmap_s // PDF object map
|
||||
typedef struct _pdfio_strbuf_s // PDF string buffer
|
||||
{
|
||||
struct _pdfio_strbuf_s *next; // Next string buffer
|
||||
pdfio_file_t *pdf; // PDF file
|
||||
bool bufused; // Is this string buffer being used?
|
||||
char buffer[PDFIO_MAX_STRING + 32],
|
||||
char buffer[PDFIO_MAX_STRING + 32];
|
||||
// String buffer
|
||||
*bufptr; // Pointer into buffer
|
||||
} _pdfio_strbuf_t;
|
||||
|
||||
struct _pdfio_file_s // PDF file structure
|
||||
@@ -290,7 +239,6 @@ struct _pdfio_file_s // PDF file structure
|
||||
unsigned char file_id[32]; // File identifier bytes
|
||||
struct lconv *loc; // Locale data
|
||||
char *version; // Version number
|
||||
_pdfio_profile_t profile; // PDF profile, if any
|
||||
pdfio_rect_t media_box, // Default MediaBox value
|
||||
crop_box; // Default CropBox value
|
||||
_pdfio_mode_t mode; // Read/write mode
|
||||
@@ -319,17 +267,11 @@ struct _pdfio_file_s // PDF file structure
|
||||
pdfio_obj_t *root_obj; // Root object/dictionary
|
||||
pdfio_obj_t *info_obj; // Information object
|
||||
pdfio_obj_t *pages_obj; // Root pages object
|
||||
pdfio_obj_t *encrypt_obj; // Encryption object (not used for reading)
|
||||
pdfio_dict_t *encrypt_dict; // De/Encryption dictionary
|
||||
pdfio_obj_t *cgats001_obj, // CGATS001 ICC profile object
|
||||
*cp1252_obj, // CP1252 font encoding object
|
||||
*unicode_obj, // Unicode font encoding object
|
||||
*objstm_obj; // Object stream object
|
||||
pdfio_dict_t *objstm_dict; // Object stream dictionary
|
||||
size_t num_objstm; // Number of objects in object stream
|
||||
pdfio_obj_t *encrypt_obj; // De/Encryption object/dictionary
|
||||
pdfio_obj_t *cp1252_obj, // CP1252 font encoding object
|
||||
*unicode_obj; // Unicode font encoding object
|
||||
pdfio_array_t *id_array; // ID array
|
||||
bool encrypt_metadata; // Encrypt metadata?
|
||||
pdfio_dict_t *markinfo; // MarkInfo dictionary, if any
|
||||
|
||||
// Allocated data elements
|
||||
size_t num_arrays, // Number of arrays
|
||||
@@ -366,9 +308,6 @@ struct _pdfio_obj_s // Object
|
||||
size_t stream_length; // Length of stream, if any
|
||||
_pdfio_value_t value; // Dictionary/number/etc. value
|
||||
pdfio_stream_t *stream; // Open stream, if any
|
||||
size_t objstm_number; // Object stream number
|
||||
char *objstm_data; // Object stream data, if any
|
||||
size_t objstm_datalen; // Object stream data length
|
||||
void *data; // Extension data, if any
|
||||
_pdfio_extfree_t datafree; // Free callback for extension data
|
||||
};
|
||||
@@ -383,20 +322,12 @@ struct _pdfio_stream_s // Stream
|
||||
char buffer[8192], // Read/write buffer
|
||||
*bufptr, // Current position in buffer
|
||||
*bufend; // End of buffer
|
||||
size_t a85size; // Size of ASCII85Decode buffer
|
||||
char *a85buffer, // ASCII85Decode buffer, if any
|
||||
*a85bufptr, // Pointer into ASCII85Decode buffer
|
||||
*a85bufend, // End of data in ASCII85Decode buffer
|
||||
a85decode[4], // Current block of decoded characters
|
||||
*a85decptr, // Pointer into decoded characters
|
||||
*a85decend; // Last decoded character
|
||||
z_stream flate; // Flate filter state
|
||||
_pdfio_lzw_t *lzw; // LZW filter state
|
||||
_pdfio_predictor_t predictor; // Predictor function, if any
|
||||
size_t pbpixel, // Size of a pixel in bytes
|
||||
pbsize, // Predictor buffer size, if any
|
||||
cbsize; // Compressed data buffer size
|
||||
uint8_t *cbuffer, // Compressed data buffer
|
||||
unsigned char *cbuffer, // Compressed data buffer
|
||||
*prbuffer, // Raw buffer (previous line), as needed
|
||||
*psbuffer; // PNG filter buffer, as needed
|
||||
_pdfio_crypto_cb_t crypto_cb; // Encryption/descryption callback, if any
|
||||
@@ -418,7 +349,7 @@ extern void _pdfioArrayDebug(pdfio_array_t *a, FILE *fp) _PDFIO_INTERNAL;
|
||||
extern void _pdfioArrayDelete(pdfio_array_t *a) _PDFIO_INTERNAL;
|
||||
extern _pdfio_value_t *_pdfioArrayGetValue(pdfio_array_t *a, size_t n) _PDFIO_INTERNAL;
|
||||
extern pdfio_array_t *_pdfioArrayRead(pdfio_file_t *pdf, pdfio_obj_t *obj, _pdfio_token_t *ts, size_t depth) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioArrayWrite(_pdfio_printf_t cb, void *cbdata, pdfio_obj_t *obj, pdfio_array_t *a) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioArrayWrite(pdfio_array_t *a, pdfio_obj_t *obj) _PDFIO_INTERNAL;
|
||||
|
||||
extern void _pdfioCryptoAESInit(_pdfio_aes_t *ctx, const uint8_t *key, size_t keylen, const uint8_t *iv) _PDFIO_INTERNAL;
|
||||
extern size_t _pdfioCryptoAESDecrypt(_pdfio_aes_t *ctx, uint8_t *outbuffer, const uint8_t *inbuffer, size_t len) _PDFIO_INTERNAL;
|
||||
@@ -443,7 +374,7 @@ extern void _pdfioDictDelete(pdfio_dict_t *dict) _PDFIO_INTERNAL;
|
||||
extern _pdfio_value_t *_pdfioDictGetValue(pdfio_dict_t *dict, const char *key) _PDFIO_INTERNAL;
|
||||
extern pdfio_dict_t *_pdfioDictRead(pdfio_file_t *pdf, pdfio_obj_t *obj, _pdfio_token_t *ts, size_t depth) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioDictSetValue(pdfio_dict_t *dict, const char *key, _pdfio_value_t *value) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioDictWrite(_pdfio_printf_t cb, void *cbdata, pdfio_obj_t *obj, pdfio_dict_t *dict, off_t *length) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioDictWrite(pdfio_dict_t *dict, pdfio_obj_t *obj, off_t *length) _PDFIO_INTERNAL;
|
||||
|
||||
extern bool _pdfioFileAddMappedObj(pdfio_file_t *pdf, pdfio_obj_t *dst_obj, pdfio_obj_t *src_obj) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioFileAddPage(pdfio_file_t *pdf, pdfio_obj_t *obj) _PDFIO_INTERNAL;
|
||||
@@ -463,10 +394,6 @@ extern off_t _pdfioFileSeek(pdfio_file_t *pdf, off_t offset, int whence) _PDFIO
|
||||
extern off_t _pdfioFileTell(pdfio_file_t *pdf) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioFileWrite(pdfio_file_t *pdf, const void *buffer, size_t bytes) _PDFIO_INTERNAL;
|
||||
|
||||
extern _pdfio_lzw_t *_pdfioLZWCreate(int def_code_size, int early, bool reversed) _PDFIO_INTERNAL;
|
||||
extern void _pdfioLZWDelete(_pdfio_lzw_t *lzw) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioLZWInflate(_pdfio_lzw_t *lzw) _PDFIO_INTERNAL;
|
||||
|
||||
extern void _pdfioObjDelete(pdfio_obj_t *obj) _PDFIO_INTERNAL;
|
||||
extern void *_pdfioObjGetExtension(pdfio_obj_t *obj) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioObjLoad(pdfio_obj_t *obj) _PDFIO_INTERNAL;
|
||||
@@ -476,10 +403,9 @@ extern bool _pdfioObjWriteHeader(pdfio_obj_t *obj) _PDFIO_INTERNAL;
|
||||
extern pdfio_stream_t *_pdfioStreamCreate(pdfio_obj_t *obj, pdfio_obj_t *length_obj, size_t cbsize, pdfio_filter_t compression) _PDFIO_INTERNAL;
|
||||
extern pdfio_stream_t *_pdfioStreamOpen(pdfio_obj_t *obj, bool decode) _PDFIO_INTERNAL;
|
||||
|
||||
extern char *_pdfioStringAllocBuffer(pdfio_file_t *pdf, _pdfio_strbuf_t **bptr);
|
||||
extern char *_pdfioStringAllocBuffer(pdfio_file_t *pdf);
|
||||
extern void _pdfioStringFreeBuffer(pdfio_file_t *pdf, char *buffer);
|
||||
extern bool _pdfioStringIsAllocated(pdfio_file_t *pdf, const char *s) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioStringPrintf(_pdfio_strbuf_t *bptr, const char *format, ...) _PDFIO_INTERNAL;
|
||||
|
||||
extern void _pdfioTokenClear(_pdfio_token_t *tb) _PDFIO_INTERNAL;
|
||||
extern void _pdfioTokenFlush(_pdfio_token_t *tb) _PDFIO_INTERNAL;
|
||||
@@ -493,7 +419,7 @@ extern bool _pdfioValueDecrypt(pdfio_file_t *pdf, pdfio_obj_t *obj, _pdfio_valu
|
||||
extern void _pdfioValueDebug(_pdfio_value_t *v, FILE *fp) _PDFIO_INTERNAL;
|
||||
extern void _pdfioValueDelete(_pdfio_value_t *v) _PDFIO_INTERNAL;
|
||||
extern _pdfio_value_t *_pdfioValueRead(pdfio_file_t *pdf, pdfio_obj_t *obj, _pdfio_token_t *ts, _pdfio_value_t *v, size_t depth) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioValueWrite(_pdfio_printf_t cb, void *cbdata, pdfio_obj_t *obj, _pdfio_value_t *v, off_t *length) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioValueWrite(pdfio_file_t *pdf, pdfio_obj_t *obj, _pdfio_value_t *v, off_t *length) _PDFIO_INTERNAL;
|
||||
|
||||
|
||||
#endif // !PDFIO_PRIVATE_H
|
||||
|
||||
529
pdfio-stream.c
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// PDF stream functions for PDFio.
|
||||
//
|
||||
// Copyright © 2021-2026 by Michael R Sweet.
|
||||
// Copyright © 2021-2025 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -14,8 +14,6 @@
|
||||
// Local functions...
|
||||
//
|
||||
|
||||
static ssize_t stream_get_bytes(pdfio_stream_t *st, void *buffer, size_t bytes);
|
||||
static ssize_t stream_inflate(pdfio_stream_t *st, uint8_t *buffer, size_t bytes, bool exactly);
|
||||
static unsigned char stream_paeth(unsigned char a, unsigned char b, unsigned char c);
|
||||
static ssize_t stream_read(pdfio_stream_t *st, char *buffer, size_t bytes);
|
||||
static bool stream_write(pdfio_stream_t *st, const void *buffer, size_t bytes);
|
||||
@@ -41,8 +39,6 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream
|
||||
{
|
||||
if (st->filter == PDFIO_FILTER_FLATE)
|
||||
inflateEnd(&(st->flate));
|
||||
else if (st->filter == PDFIO_FILTER_LZW)
|
||||
_pdfioLZWDelete(st->lzw);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -176,7 +172,6 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream
|
||||
|
||||
st->pdf->current_obj = NULL;
|
||||
|
||||
free(st->a85buffer);
|
||||
free(st->cbuffer);
|
||||
free(st->prbuffer);
|
||||
free(st->psbuffer);
|
||||
@@ -432,7 +427,7 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
|
||||
const char *type; // Object type
|
||||
|
||||
|
||||
PDFIO_DEBUG("_pdfioStreamOpen(obj=%p(%u), decode=%s)\n", (void *)obj, (unsigned)obj->number, decode ? "true" : "false");
|
||||
PDFIO_DEBUG("_pdfioStreamOpen(obj=%p(%u), decode=%s)\n", obj, (unsigned)obj->number, decode ? "true" : "false");
|
||||
|
||||
// Allocate a new stream object...
|
||||
if ((st = (pdfio_stream_t *)calloc(1, sizeof(pdfio_stream_t))) == NULL)
|
||||
@@ -484,34 +479,10 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
|
||||
pdfio_array_t *fa = pdfioDictGetArray(dict, "Filter");
|
||||
// Filter array
|
||||
|
||||
if (!filter && fa)
|
||||
if (!filter && fa && pdfioArrayGetSize(fa) == 1)
|
||||
{
|
||||
const char *filter0 = pdfioArrayGetName(fa, 0);
|
||||
// First filter
|
||||
|
||||
if (pdfioArrayGetSize(fa) == 1)
|
||||
{
|
||||
// Support single-valued arrays...
|
||||
filter = filter0;
|
||||
}
|
||||
else if (pdfioArrayGetSize(fa) == 2 && filter0 && !strcmp(filter0, "ASCII85Decode"))
|
||||
{
|
||||
// Support ASCII85Decode + something else
|
||||
st->a85size = 5200; // Enough for 4k of decoded data
|
||||
|
||||
// Allocate the ASCII85Decode buffer...
|
||||
if ((st->a85buffer = malloc(st->a85size)) == NULL)
|
||||
{
|
||||
_pdfioFileError(st->pdf, "Unable to allocate ASCII85Decode buffer.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
st->a85bufptr = st->a85buffer;
|
||||
st->a85bufend = st->a85buffer;
|
||||
|
||||
// Get the second filter...
|
||||
filter = pdfioArrayGetName(fa, 1);
|
||||
}
|
||||
// Support single-valued arrays...
|
||||
filter = pdfioArrayGetName(fa, 0);
|
||||
}
|
||||
|
||||
if (!filter)
|
||||
@@ -519,6 +490,7 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
|
||||
// No single filter name, do we have a compound filter?
|
||||
if (fa)
|
||||
{
|
||||
// TODO: Implement compound filters...
|
||||
_pdfioFileError(st->pdf, "Unsupported compound stream filter.");
|
||||
goto error;
|
||||
}
|
||||
@@ -526,9 +498,9 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
|
||||
// No filter, read as-is...
|
||||
st->filter = PDFIO_FILTER_NONE;
|
||||
}
|
||||
else if (!strcmp(filter, "FlateDecode") || !strcmp(filter, "LZWDecode"))
|
||||
else if (!strcmp(filter, "FlateDecode"))
|
||||
{
|
||||
// Flate or LZW compression
|
||||
// Flate compression
|
||||
pdfio_dict_t *params = pdfioDictGetDict(dict, "DecodeParms");
|
||||
// Decoding parameters
|
||||
int bpc = (int)pdfioDictGetNumber(params, "BitsPerComponent");
|
||||
@@ -539,11 +511,12 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
|
||||
// Number of columns
|
||||
int predictor = (int)pdfioDictGetNumber(params, "Predictor");
|
||||
// Predictory value, if any
|
||||
int status; // ZLIB status
|
||||
ssize_t rbytes; // Bytes read
|
||||
|
||||
PDFIO_DEBUG("_pdfioStreamOpen: %s - BitsPerComponent=%d, Colors=%d, Columns=%d, Predictor=%d\n", filter, bpc, colors, columns, predictor);
|
||||
PDFIO_DEBUG("_pdfioStreamOpen: FlateDecode - BitsPerComponent=%d, Colors=%d, Columns=%d, Predictor=%d\n", bpc, colors, columns, predictor);
|
||||
|
||||
st->filter = !strcmp(filter, "FlateDecode") ? PDFIO_FILTER_FLATE : PDFIO_FILTER_LZW;
|
||||
st->filter = PDFIO_FILTER_FLATE;
|
||||
|
||||
if (bpc == 0)
|
||||
{
|
||||
@@ -610,62 +583,47 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
|
||||
st->cbsize = 4096;
|
||||
if ((st->cbuffer = malloc(st->cbsize)) == NULL)
|
||||
{
|
||||
_pdfioFileError(st->pdf, "Unable to allocate %lu bytes for FlateDecode decompression buffer.", (unsigned long)st->cbsize);
|
||||
_pdfioFileError(st->pdf, "Unable to allocate %lu bytes for Flate compression buffer.", (unsigned long)st->cbsize);
|
||||
goto error;
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("_pdfioStreamOpen: pos=%ld\n", (long)_pdfioFileTell(st->pdf));
|
||||
if ((rbytes = stream_get_bytes(st, st->cbuffer, st->cbsize)) <= 0)
|
||||
if (st->cbsize > st->remaining)
|
||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
|
||||
else
|
||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->cbsize);
|
||||
|
||||
if (rbytes <= 0)
|
||||
{
|
||||
_pdfioFileError(st->pdf, "Unable to read bytes for stream.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (st->filter == PDFIO_FILTER_FLATE)
|
||||
if (st->crypto_cb)
|
||||
rbytes = (ssize_t)(st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, (size_t)rbytes);
|
||||
|
||||
st->flate.next_in = (Bytef *)st->cbuffer;
|
||||
st->flate.avail_in = (uInt)rbytes;
|
||||
|
||||
PDFIO_DEBUG("_pdfioStreamOpen: avail_in=%u, cbuffer=<%02X%02X%02X%02X%02X%02X%02X%02X...>\n", st->flate.avail_in, st->cbuffer[0], st->cbuffer[1], st->cbuffer[2], st->cbuffer[3], st->cbuffer[4], st->cbuffer[5], st->cbuffer[6], st->cbuffer[7]);
|
||||
|
||||
if ((status = inflateInit(&(st->flate))) != Z_OK)
|
||||
{
|
||||
// Flate decompression...
|
||||
int status; // ZLIB status
|
||||
|
||||
st->flate.next_in = (Bytef *)st->cbuffer;
|
||||
st->flate.avail_in = (uInt)rbytes;
|
||||
|
||||
PDFIO_DEBUG("_pdfioStreamOpen: avail_in=%u, cbuffer=<%02X%02X%02X%02X%02X%02X%02X%02X...>\n", st->flate.avail_in, st->cbuffer[0], st->cbuffer[1], st->cbuffer[2], st->cbuffer[3], st->cbuffer[4], st->cbuffer[5], st->cbuffer[6], st->cbuffer[7]);
|
||||
|
||||
if ((status = inflateInit(&(st->flate))) != Z_OK)
|
||||
{
|
||||
_pdfioFileError(st->pdf, "Unable to start FlateDecode filter: %s", zstrerror(status));
|
||||
goto error;
|
||||
}
|
||||
_pdfioFileError(st->pdf, "Unable to start Flate filter: %s", zstrerror(status));
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
// LZW decompression...
|
||||
int early = 1;
|
||||
|
||||
if (pdfioDictGetType(params, "EarlyChange") == PDFIO_VALTYPE_NUMBER)
|
||||
{
|
||||
early = (int)pdfioDictGetNumber(params, "EarlyChange");
|
||||
if (early < 0 || early > 100)
|
||||
{
|
||||
_pdfioFileError(st->pdf, "Bad EarlyChange value %d for LZWDecode filter.", early);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if ((st->lzw = _pdfioLZWCreate(/*code_size*/8, early, /*reversed*/false)) == NULL)
|
||||
{
|
||||
_pdfioFileError(st->pdf, "Unable to initialize LZWDecode filter: %s", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
st->lzw->next_in = st->cbuffer;
|
||||
st->lzw->avail_in = (size_t)rbytes;
|
||||
}
|
||||
st->remaining -= st->flate.avail_in;
|
||||
}
|
||||
else if (!strcmp(filter, "LZWDecode"))
|
||||
{
|
||||
// LZW compression
|
||||
st->filter = PDFIO_FILTER_LZW;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Something else we don't support
|
||||
_pdfioFileError(st->pdf, "Unsupported stream filter '/%s'.", filter);
|
||||
_pdfioFileError(st->pdf, "Unsupported stream filter '%N'.", filter);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -680,13 +638,12 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
|
||||
// If we get here something went wrong...
|
||||
error:
|
||||
|
||||
free(st->a85buffer);
|
||||
free(st->cbuffer);
|
||||
free(st->prbuffer);
|
||||
free(st->psbuffer);
|
||||
free(st);
|
||||
|
||||
return (NULL);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -891,7 +848,7 @@ pdfioStreamWrite(
|
||||
*pptr; // Previous raw buffer
|
||||
|
||||
|
||||
PDFIO_DEBUG("pdfioStreamWrite(st=%p, buffer=%p, bytes=%lu)\n", (void *)st, buffer, (unsigned long)bytes);
|
||||
PDFIO_DEBUG("pdfioStreamWrite(st=%p, buffer=%p, bytes=%lu)\n", st, buffer, (unsigned long)bytes);
|
||||
|
||||
// Range check input...
|
||||
if (!st || st->pdf->mode != _PDFIO_MODE_WRITE || !buffer || !bytes)
|
||||
@@ -1054,271 +1011,6 @@ pdfioStreamWrite(
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'stream_get_bytes()' - Read and decrypt raw or ASCII85Decode-encoded data.
|
||||
//
|
||||
|
||||
static ssize_t // O - Bytes read or `-1` on error
|
||||
stream_get_bytes(
|
||||
pdfio_stream_t *st, // I - Stream
|
||||
void *buffer, // I - Buffer
|
||||
size_t bytes) // I - Maximum number of bytes to read
|
||||
{
|
||||
ssize_t rbytes; // Bytes read
|
||||
|
||||
|
||||
if (st->a85buffer)
|
||||
{
|
||||
// Decode through the ASCII85Decode buffer...
|
||||
char *bufptr = (char *)buffer; // Pointer into read buffer
|
||||
|
||||
rbytes = 0;
|
||||
|
||||
// Read as much as we can...
|
||||
while (bytes > 0 && (st->a85bufptr < st->a85bufend || st->remaining > 0))
|
||||
{
|
||||
unsigned count, // Number of ASCII85 chars
|
||||
a85val; // ASCII85 "chunk" value
|
||||
char *a85bufptr; // Local copy of buffer pointer
|
||||
size_t declen; // Decoded length
|
||||
|
||||
|
||||
// First use up any remaining decoded chars...
|
||||
if (st->a85decptr)
|
||||
{
|
||||
declen = (size_t)(st->a85decend - st->a85decptr);
|
||||
|
||||
if (bytes >= declen)
|
||||
{
|
||||
memcpy(bufptr, st->a85decptr, declen);
|
||||
bufptr += declen;
|
||||
rbytes += (ssize_t)declen;
|
||||
st->a85decptr = NULL;
|
||||
bytes -= declen;
|
||||
|
||||
if (bytes == 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(bufptr, st->a85decptr, bytes);
|
||||
rbytes += (ssize_t)bytes;
|
||||
st->a85decptr += bytes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((st->a85bufend - st->a85bufptr) < 5 && st->remaining > 0)
|
||||
{
|
||||
// Fill the ASCII85Decode buffer...
|
||||
ssize_t a85bytes = st->a85bufend - st->a85bufptr;
|
||||
// Bytes in the ASCII85Decode buffer
|
||||
size_t a85remaining = st->a85size - (size_t)a85bytes;
|
||||
// Remaining capacity in the buffer
|
||||
|
||||
// First move any remaining bytes to the front of the buffer...
|
||||
if (a85bytes > 0)
|
||||
memmove(st->a85buffer, st->a85bufptr, (size_t)a85bytes);
|
||||
|
||||
st->a85bufptr = st->a85buffer;
|
||||
st->a85bufend = st->a85buffer + a85bytes;
|
||||
|
||||
// Then read more data from the file...
|
||||
if (a85remaining > st->remaining)
|
||||
a85bytes = _pdfioFileRead(st->pdf, st->a85bufend, st->remaining);
|
||||
else
|
||||
a85bytes = _pdfioFileRead(st->pdf, st->a85bufend, a85remaining);
|
||||
|
||||
if (a85bytes > 0)
|
||||
{
|
||||
st->remaining -= (size_t)a85bytes;
|
||||
|
||||
if (st->crypto_cb)
|
||||
(st->crypto_cb)(&st->crypto_ctx, (uint8_t *)st->a85bufend, (uint8_t *)st->a85bufend, (size_t)a85bytes);
|
||||
|
||||
st->a85bufend += a85bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
_pdfioFileError(st->pdf, "Read error in stream.");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
// Grab the next chunk...
|
||||
for (a85bufptr = st->a85bufptr, a85val = 0, count = 0; a85bufptr < st->a85bufend && count < 5; a85bufptr ++)
|
||||
{
|
||||
char a85ch = *a85bufptr; // Current character
|
||||
|
||||
if (a85ch >= '!' && a85ch <= 'u')
|
||||
{
|
||||
// Valid ASCII85Decode character...
|
||||
a85val = a85val * 85 + (unsigned)a85ch - '!';
|
||||
count ++;
|
||||
}
|
||||
else if (a85ch == 'z' && count == 0)
|
||||
{
|
||||
// 'z' == 0's
|
||||
a85val = 0;
|
||||
count = 5;
|
||||
|
||||
a85bufptr++;
|
||||
}
|
||||
else if (a85ch == '~')
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (!isspace(a85ch & 255))
|
||||
{
|
||||
// Invalid ASCII85Decode character...
|
||||
_pdfioFileError(st->pdf, "Invalid ASCII85Decode character '%c' in stream.", a85ch);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
st->a85bufptr = a85bufptr;
|
||||
|
||||
if (*a85bufptr == '~')
|
||||
break;
|
||||
|
||||
if (count < 2)
|
||||
{
|
||||
// Need at least 2 characters to decode a single byte...
|
||||
_pdfioFileError(st->pdf, "Invalid ASCII85Decode sequence in stream.");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
declen = count - 1;
|
||||
|
||||
// Add rounds to properly align the decoded value...
|
||||
while (count < 5)
|
||||
{
|
||||
a85val = a85val * 85 + 84;
|
||||
count ++;
|
||||
}
|
||||
|
||||
// Copy the bytes to the decode buffer...
|
||||
st->a85decode[0] = (char)(a85val >> 24);
|
||||
st->a85decode[1] = (char)((a85val >> 16) & 255);
|
||||
st->a85decode[2] = (char)((a85val >> 8) & 255);
|
||||
st->a85decode[3] = (char)(a85val & 255);
|
||||
|
||||
st->a85decptr = st->a85decode;
|
||||
st->a85decend = st->a85decode + declen;
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("stream_get_bytes: Returning %ld ASCII85 bytes for stream.\n", (long)rbytes);
|
||||
|
||||
return (rbytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Limit reads to the length of the stream...
|
||||
if (bytes > st->remaining)
|
||||
rbytes = _pdfioFileRead(st->pdf, buffer, st->remaining);
|
||||
else
|
||||
rbytes = _pdfioFileRead(st->pdf, buffer, bytes);
|
||||
|
||||
if (rbytes > 0)
|
||||
{
|
||||
st->remaining -= (size_t)rbytes;
|
||||
|
||||
if (st->crypto_cb)
|
||||
(st->crypto_cb)(&st->crypto_ctx, (uint8_t *)buffer, (uint8_t *)buffer, (size_t)rbytes);
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("stream_get_bytes: Returning %ld raw bytes for stream.\n", (long)rbytes);
|
||||
|
||||
return (rbytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'stream_inflate()' - Decompress bytes from a stream (Flate or LZW) into the specified buffer.
|
||||
//
|
||||
|
||||
static ssize_t
|
||||
stream_inflate(pdfio_stream_t *st, // I - Stream
|
||||
uint8_t *buffer, // I - Output buffer
|
||||
size_t bytes, // I - Number of bytes
|
||||
bool exactly) // I - Require exactly the number of bytes
|
||||
{
|
||||
ssize_t rbytes; // Bytes read
|
||||
|
||||
|
||||
// Setup decompression to the output buffer...
|
||||
if (st->filter == PDFIO_FILTER_FLATE)
|
||||
{
|
||||
st->flate.next_out = (Bytef *)buffer;
|
||||
st->flate.avail_out = (uInt)bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
st->lzw->next_out = buffer;
|
||||
st->lzw->avail_out = bytes;
|
||||
}
|
||||
|
||||
// Loop to get the bytes...
|
||||
do
|
||||
{
|
||||
if (st->filter == PDFIO_FILTER_FLATE)
|
||||
{
|
||||
// Flate decompress
|
||||
int status; // Status of decompression
|
||||
|
||||
PDFIO_DEBUG("stream_inflate: avail_in=%u, avail_out=%u\n", st->flate.avail_in, st->flate.avail_out);
|
||||
|
||||
if (st->flate.avail_in == 0)
|
||||
{
|
||||
// Read more from the file...
|
||||
if ((rbytes = stream_get_bytes(st, st->cbuffer, st->cbsize)) <= 0)
|
||||
return (-1); // End of file...
|
||||
|
||||
st->flate.next_in = (Bytef *)st->cbuffer;
|
||||
st->flate.avail_in = (uInt)rbytes;
|
||||
}
|
||||
|
||||
if ((status = inflate(&(st->flate), Z_NO_FLUSH)) < Z_OK)
|
||||
{
|
||||
PDFIO_DEBUG("stream_inflate: inflate() returned %d\n", status);
|
||||
_pdfioFileError(st->pdf, "Unable to decompress stream data for object %ld: %s", (long)st->obj->number, zstrerror(status));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bytes = (size_t)st->flate.avail_out;
|
||||
}
|
||||
else
|
||||
{
|
||||
// LZW decompress
|
||||
if (st->lzw->avail_in == 0)
|
||||
{
|
||||
// Read more from the file...
|
||||
if ((rbytes = stream_get_bytes(st, st->cbuffer, st->cbsize)) <= 0)
|
||||
return (-1); // End of file...
|
||||
|
||||
st->lzw->next_in = st->cbuffer;
|
||||
st->lzw->avail_in = (size_t)rbytes;
|
||||
}
|
||||
|
||||
if (!_pdfioLZWInflate(st->lzw) && !st->lzw->saw_eod)
|
||||
{
|
||||
_pdfioFileError(st->pdf, "Unable to decompress stream data for object %ld: %s", (long)st->obj->number, st->lzw->error);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bytes = st->lzw->avail_out;
|
||||
}
|
||||
}
|
||||
while (bytes > 0 && exactly);
|
||||
|
||||
if (st->filter == PDFIO_FILTER_FLATE)
|
||||
return (st->flate.next_out - (Bytef *)buffer);
|
||||
else
|
||||
return (st->lzw->next_out - (uint8_t *)buffer);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'stream_paeth()' - PaethPredictor function for PNG decompression filter.
|
||||
//
|
||||
@@ -1346,20 +1038,67 @@ stream_read(pdfio_stream_t *st, // I - Stream
|
||||
char *buffer, // I - Buffer
|
||||
size_t bytes) // I - Number of bytes to read
|
||||
{
|
||||
ssize_t rbytes; // Bytes read
|
||||
uInt avail_in, avail_out; // Previous flate values
|
||||
|
||||
|
||||
if (st->filter == PDFIO_FILTER_NONE)
|
||||
{
|
||||
// No filtering...
|
||||
return (stream_get_bytes(st, buffer, bytes));
|
||||
// No filtering, but limit reads to the length of the stream...
|
||||
if (bytes > st->remaining)
|
||||
rbytes = _pdfioFileRead(st->pdf, buffer, st->remaining);
|
||||
else
|
||||
rbytes = _pdfioFileRead(st->pdf, buffer, bytes);
|
||||
|
||||
if (rbytes > 0)
|
||||
{
|
||||
st->remaining -= (size_t)rbytes;
|
||||
|
||||
if (st->crypto_cb)
|
||||
(st->crypto_cb)(&st->crypto_ctx, (uint8_t *)buffer, (uint8_t *)buffer, (size_t)rbytes);
|
||||
}
|
||||
|
||||
return (rbytes);
|
||||
}
|
||||
else if (st->filter == PDFIO_FILTER_FLATE || st->filter == PDFIO_FILTER_LZW)
|
||||
else if (st->filter == PDFIO_FILTER_FLATE)
|
||||
{
|
||||
// Flate or LZW compression...
|
||||
// Deflate compression...
|
||||
int status; // Status of decompression
|
||||
|
||||
if (st->predictor == _PDFIO_PREDICTOR_NONE)
|
||||
{
|
||||
// Decompress into the buffer...
|
||||
PDFIO_DEBUG("stream_read: No predictor.\n");
|
||||
|
||||
return (stream_inflate(st, (uint8_t *)buffer, bytes, /*exactly*/false));
|
||||
if (st->flate.avail_in == 0)
|
||||
{
|
||||
// Read more from the file...
|
||||
if (st->cbsize > st->remaining)
|
||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
|
||||
else
|
||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->cbsize);
|
||||
|
||||
if (rbytes <= 0)
|
||||
return (-1); // End of file...
|
||||
|
||||
if (st->crypto_cb)
|
||||
rbytes = (ssize_t)(st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, (size_t)rbytes);
|
||||
|
||||
st->remaining -= (size_t)rbytes;
|
||||
st->flate.next_in = (Bytef *)st->cbuffer;
|
||||
st->flate.avail_in = (uInt)rbytes;
|
||||
}
|
||||
|
||||
st->flate.next_out = (Bytef *)buffer;
|
||||
st->flate.avail_out = (uInt)bytes;
|
||||
|
||||
if ((status = inflate(&(st->flate), Z_NO_FLUSH)) < Z_OK)
|
||||
{
|
||||
_pdfioFileError(st->pdf, "Unable to decompress stream data for object %ld: %s", (long)st->obj->number, zstrerror(status));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (st->flate.next_out - (Bytef *)buffer);
|
||||
}
|
||||
else if (st->predictor == _PDFIO_PREDICTOR_TIFF2)
|
||||
{
|
||||
@@ -1367,9 +1106,9 @@ stream_read(pdfio_stream_t *st, // I - Stream
|
||||
// Size of pixel in bytes
|
||||
remaining = st->pbsize;
|
||||
// Remaining bytes
|
||||
uint8_t *bufptr = (uint8_t *)buffer,
|
||||
unsigned char *bufptr = (unsigned char *)buffer,
|
||||
// Pointer into buffer
|
||||
*bufsecond = (uint8_t *)buffer + pbpixel,
|
||||
*bufsecond = (unsigned char *)buffer + pbpixel,
|
||||
// Pointer to second pixel in buffer
|
||||
*sptr = st->psbuffer;
|
||||
// Current (raw) line
|
||||
@@ -1382,7 +1121,43 @@ stream_read(pdfio_stream_t *st, // I - Stream
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (stream_inflate(st, sptr, st->pbsize, /*exactly*/true) < 0)
|
||||
st->flate.next_out = (Bytef *)sptr;
|
||||
st->flate.avail_out = (uInt)st->pbsize;
|
||||
|
||||
while (st->flate.avail_out > 0)
|
||||
{
|
||||
if (st->flate.avail_in == 0)
|
||||
{
|
||||
// Read more from the file...
|
||||
if (st->cbsize > st->remaining)
|
||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
|
||||
else
|
||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->cbsize);
|
||||
|
||||
if (rbytes <= 0)
|
||||
return (-1); // End of file...
|
||||
|
||||
if (st->crypto_cb)
|
||||
rbytes = (ssize_t)(st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, (size_t)rbytes);
|
||||
|
||||
st->remaining -= (size_t)rbytes;
|
||||
st->flate.next_in = (Bytef *)st->cbuffer;
|
||||
st->flate.avail_in = (uInt)rbytes;
|
||||
}
|
||||
|
||||
avail_in = st->flate.avail_in;
|
||||
avail_out = st->flate.avail_out;
|
||||
|
||||
if ((status = inflate(&(st->flate), Z_NO_FLUSH)) < Z_OK)
|
||||
{
|
||||
_pdfioFileError(st->pdf, "Unable to decompress stream data for object %ld: %s", (long)st->obj->number, zstrerror(status));
|
||||
return (-1);
|
||||
}
|
||||
else if (status == Z_STREAM_END || (avail_in == st->flate.avail_in && avail_out == st->flate.avail_out))
|
||||
break;
|
||||
}
|
||||
|
||||
if (st->flate.avail_out > 0)
|
||||
return (-1); // Early end of stream
|
||||
|
||||
for (; bufptr < bufsecond; remaining --, sptr ++)
|
||||
@@ -1399,9 +1174,9 @@ stream_read(pdfio_stream_t *st, // I - Stream
|
||||
// Size of pixel in bytes
|
||||
remaining = st->pbsize - 1;
|
||||
// Remaining bytes
|
||||
uint8_t *bufptr = (uint8_t *)buffer,
|
||||
unsigned char *bufptr = (unsigned char *)buffer,
|
||||
// Pointer into buffer
|
||||
*bufsecond = (uint8_t *)buffer + pbpixel,
|
||||
*bufsecond = (unsigned char *)buffer + pbpixel,
|
||||
// Pointer to second pixel in buffer
|
||||
*sptr = st->psbuffer + 1,
|
||||
// Current (raw) line
|
||||
@@ -1416,10 +1191,46 @@ stream_read(pdfio_stream_t *st, // I - Stream
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (stream_inflate(st, sptr - 1, st->pbsize, /*exactly*/true) < 0)
|
||||
st->flate.next_out = (Bytef *)sptr - 1;
|
||||
st->flate.avail_out = (uInt)st->pbsize;
|
||||
|
||||
while (st->flate.avail_out > 0)
|
||||
{
|
||||
if (st->flate.avail_in == 0)
|
||||
{
|
||||
// Read more from the file...
|
||||
if (st->cbsize > st->remaining)
|
||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
|
||||
else
|
||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->cbsize);
|
||||
|
||||
if (rbytes <= 0)
|
||||
return (-1); // End of file...
|
||||
|
||||
if (st->crypto_cb)
|
||||
rbytes = (ssize_t)(st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, (size_t)rbytes);
|
||||
|
||||
st->remaining -= (size_t)rbytes;
|
||||
st->flate.next_in = (Bytef *)st->cbuffer;
|
||||
st->flate.avail_in = (uInt)rbytes;
|
||||
}
|
||||
|
||||
avail_in = st->flate.avail_in;
|
||||
avail_out = st->flate.avail_out;
|
||||
|
||||
if ((status = inflate(&(st->flate), Z_NO_FLUSH)) < Z_OK)
|
||||
{
|
||||
_pdfioFileError(st->pdf, "Unable to decompress stream data for object %ld: %s", (long)st->obj->number, zstrerror(status));
|
||||
return (-1);
|
||||
}
|
||||
else if (status == Z_STREAM_END || (avail_in == st->flate.avail_in && avail_out == st->flate.avail_out))
|
||||
break;
|
||||
}
|
||||
|
||||
if (st->flate.avail_out > 0)
|
||||
{
|
||||
// Early end of stream
|
||||
PDFIO_DEBUG("stream_read: Early EOF (remaining=%u).\n", (unsigned)st->remaining);
|
||||
PDFIO_DEBUG("stream_read: Early EOF (remaining=%u, avail_in=%d, avail_out=%d, data_type=%d, next_in=<%02X%02X%02X%02X...>).\n", (unsigned)st->remaining, st->flate.avail_in, st->flate.avail_out, st->flate.data_type, st->flate.next_in[0], st->flate.next_in[1], st->flate.next_in[2], st->flate.next_in[3]);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@@ -1522,6 +1333,8 @@ stream_write(pdfio_stream_t *st, // I - Stream
|
||||
outbytes = cbytes;
|
||||
}
|
||||
|
||||
// fprintf(stderr, "stream_write: bytes=%u, outbytes=%u\n", (unsigned)bytes, (unsigned)outbytes);
|
||||
|
||||
if (!_pdfioFileWrite(st->pdf, st->cbuffer, outbytes))
|
||||
return (false);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// PDF string functions for PDFio.
|
||||
//
|
||||
// Copyright © 2021-2026 by Michael R Sweet.
|
||||
// Copyright © 2021-2025 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -674,8 +674,7 @@ _pdfio_vsnprintf(pdfio_file_t *pdf, // I - PDF file
|
||||
|
||||
char * // O - Buffer or `NULL` on error
|
||||
_pdfioStringAllocBuffer(
|
||||
pdfio_file_t *pdf, // I - PDF file
|
||||
_pdfio_strbuf_t **bptr) // O - String buffer pointer
|
||||
pdfio_file_t *pdf) // I - PDF file
|
||||
{
|
||||
_pdfio_strbuf_t *current; // Current string buffer
|
||||
|
||||
@@ -684,34 +683,21 @@ _pdfioStringAllocBuffer(
|
||||
for (current = pdf->strbuffers; current; current = current->next)
|
||||
{
|
||||
if (!current->bufused)
|
||||
goto done;
|
||||
{
|
||||
current->bufused = true;
|
||||
return (current->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't find one, allocate a new one...
|
||||
if ((current = calloc(1, sizeof(_pdfio_strbuf_t))) == NULL)
|
||||
{
|
||||
if (bptr)
|
||||
*bptr = NULL;
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
// Add to the linked list of string buffers...
|
||||
current->pdf = pdf;
|
||||
current->next = pdf->strbuffers;
|
||||
pdf->strbuffers = current;
|
||||
|
||||
// Claim and return the free string buffer...
|
||||
done:
|
||||
|
||||
current->next = pdf->strbuffers;
|
||||
current->bufused = true;
|
||||
|
||||
if (bptr)
|
||||
{
|
||||
*bptr = current;
|
||||
current->buffer[0] = '\0';
|
||||
current->bufptr = current->buffer;
|
||||
}
|
||||
pdf->strbuffers = current;
|
||||
|
||||
return (current->buffer);
|
||||
}
|
||||
@@ -737,7 +723,7 @@ pdfioStringCreate(
|
||||
int diff; // Different
|
||||
|
||||
|
||||
PDFIO_DEBUG("pdfioStringCreate(pdf=%p, s=\"%s\")\n", (void *)pdf, s);
|
||||
PDFIO_DEBUG("pdfioStringCreate(pdf=%p, s=\"%s\")\n", pdf, s);
|
||||
|
||||
// Range check input...
|
||||
if (!pdf || !s)
|
||||
@@ -871,36 +857,6 @@ _pdfioStringIsAllocated(
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// '_pdfioStringPrintf()' - Append a formatted string to a string buffer.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
_pdfioStringPrintf(
|
||||
_pdfio_strbuf_t *bptr, // I - String buffer
|
||||
const char *format, // I - Format string
|
||||
...) // I - Additional arguments as needed
|
||||
{
|
||||
va_list ap; // Pointer to additional arguments
|
||||
size_t remaining; // Remaining bytes
|
||||
ssize_t bytes; // Formatted bytes
|
||||
|
||||
|
||||
// Format the string in the buffer...
|
||||
va_start(ap, format);
|
||||
|
||||
remaining = sizeof(bptr->buffer) - (size_t)(bptr->bufptr - bptr->buffer);
|
||||
bytes = _pdfio_vsnprintf(bptr->pdf, bptr->bufptr, remaining, format, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
// Advance the current position in the buffer and return.
|
||||
bptr->bufptr += strlen(bptr->bufptr);
|
||||
|
||||
return (bytes < (ssize_t)remaining && bytes >= 0);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'find_string()' - Find an element in the array.
|
||||
//
|
||||
|
||||
@@ -54,7 +54,7 @@ static int get_char(_pdfio_token_t *tb);
|
||||
void
|
||||
_pdfioTokenClear(_pdfio_token_t *tb) // I - Token buffer/stack
|
||||
{
|
||||
PDFIO_DEBUG("_pdfioTokenClear(tb=%p)\n", (void *)tb);
|
||||
PDFIO_DEBUG("_pdfioTokenClear(tb=%p)\n", tb);
|
||||
|
||||
while (tb->num_tokens > 0)
|
||||
{
|
||||
@@ -132,7 +132,7 @@ _pdfioTokenGet(_pdfio_token_t *tb, // I - Token buffer/stack
|
||||
if ((len = strlen(tb->tokens[tb->num_tokens])) > (bufsize - 1))
|
||||
{
|
||||
// Value too large...
|
||||
PDFIO_DEBUG("_pdfioTokenGet(tb=%p, buffer=%p, bufsize=%u): Token '%s' from stack too large.\n", (void *)tb, (void *)buffer, (unsigned)bufsize, tb->tokens[tb->num_tokens]);
|
||||
PDFIO_DEBUG("_pdfioTokenGet(tb=%p, buffer=%p, bufsize=%u): Token '%s' from stack too large.\n", tb, buffer, (unsigned)bufsize, tb->tokens[tb->num_tokens]);
|
||||
*buffer = '\0';
|
||||
return (false);
|
||||
}
|
||||
@@ -140,7 +140,7 @@ _pdfioTokenGet(_pdfio_token_t *tb, // I - Token buffer/stack
|
||||
memcpy(buffer, tb->tokens[tb->num_tokens], len);
|
||||
buffer[len] = '\0';
|
||||
|
||||
PDFIO_DEBUG("_pdfioTokenGet(tb=%p, buffer=%p, bufsize=%u): Popping '%s' from stack.\n", (void *)tb, (void *)buffer, (unsigned)bufsize, buffer);
|
||||
PDFIO_DEBUG("_pdfioTokenGet(tb=%p, buffer=%p, bufsize=%u): Popping '%s' from stack.\n", tb, buffer, (unsigned)bufsize, buffer);
|
||||
|
||||
free(tb->tokens[tb->num_tokens]);
|
||||
tb->tokens[tb->num_tokens] = NULL;
|
||||
@@ -380,7 +380,7 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack
|
||||
else
|
||||
{
|
||||
// Out of space
|
||||
_pdfioFileError(tb->pdf, "String token too large.");
|
||||
_pdfioFileError(tb->pdf, "Token too large.");
|
||||
*bufptr = '\0';
|
||||
return (false);
|
||||
}
|
||||
@@ -393,18 +393,9 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack
|
||||
return (false);
|
||||
}
|
||||
|
||||
if ((bufptr - buffer) > 3 && ((bufptr - buffer) & 1) != 0 && (!memcmp(buffer, "(\377\376", 3) || !memcmp(buffer, "(\376\377", 3)))
|
||||
{
|
||||
// UTF-16 string, convert to UTF-8...
|
||||
PDFIO_DEBUG("_pdfioTokenRead: Converting string to UTF-8.\n", stderr);
|
||||
_pdfio_utf16cpy(buffer + 1, (unsigned char *)buffer + 1, (size_t)(bufptr - buffer - 1), bufsize - 1);
|
||||
|
||||
PDFIO_DEBUG("_pdfioTokenRead: Read '%s'.\n", buffer);
|
||||
return (true);
|
||||
}
|
||||
else if (saw_nul)
|
||||
if (saw_nul)
|
||||
{
|
||||
// Contains nul characters, convert to a hex (binary) string...
|
||||
// Convert to a hex (binary) string...
|
||||
char *litptr, // Pointer to literal character
|
||||
*hexptr; // Pointer to hex character
|
||||
size_t bytes = (size_t)(bufptr - buffer - 1);
|
||||
@@ -417,7 +408,7 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack
|
||||
if ((2 * (bytes + 1)) > bufsize)
|
||||
{
|
||||
// Out of space...
|
||||
_pdfioFileError(tb->pdf, "Binary string token too large.");
|
||||
_pdfioFileError(tb->pdf, "Token too large.");
|
||||
*bufptr = '\0';
|
||||
return (false);
|
||||
}
|
||||
@@ -451,7 +442,7 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack
|
||||
else
|
||||
{
|
||||
// Out of space...
|
||||
_pdfioFileError(tb->pdf, "Keyword token too large.");
|
||||
_pdfioFileError(tb->pdf, "Token too large.");
|
||||
*bufptr = '\0';
|
||||
return (false);
|
||||
}
|
||||
@@ -483,7 +474,7 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack
|
||||
else
|
||||
{
|
||||
// Out of space...
|
||||
_pdfioFileError(tb->pdf, "Number token too large.");
|
||||
_pdfioFileError(tb->pdf, "Token too large.");
|
||||
*bufptr = '\0';
|
||||
return (false);
|
||||
}
|
||||
@@ -532,7 +523,7 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack
|
||||
else
|
||||
{
|
||||
// Out of space
|
||||
_pdfioFileError(tb->pdf, "Name token too large.");
|
||||
_pdfioFileError(tb->pdf, "Token too large.");
|
||||
*bufptr = '\0';
|
||||
return (false);
|
||||
}
|
||||
@@ -575,7 +566,7 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack
|
||||
else
|
||||
{
|
||||
// Too large
|
||||
_pdfioFileError(tb->pdf, "Hex string token too large.");
|
||||
_pdfioFileError(tb->pdf, "Token too large.");
|
||||
*bufptr = '\0';
|
||||
return (false);
|
||||
}
|
||||
|
||||
117
pdfio-value.c
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// PDF value functions for PDFio.
|
||||
//
|
||||
// Copyright © 2021-2026 by Michael R Sweet.
|
||||
// Copyright © 2021-2025 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -46,7 +46,7 @@ _pdfioValueCopy(pdfio_file_t *pdfdst, // I - Destination PDF file
|
||||
#endif // DEBUG
|
||||
|
||||
|
||||
PDFIO_DEBUG("_pdfioValueCopy(pdfdst=%p, vdst=%p, pdfsrc=%p, vsrc=%p(%s))\n", (void *)pdfdst, (void *)vdst, (void *)pdfsrc, (void *)vsrc, types[vsrc->type]);
|
||||
PDFIO_DEBUG("_pdfioValueCopy(pdfdst=%p, vdst=%p, pdfsrc=%p, vsrc=%p(%s))\n", pdfdst, vdst, pdfsrc, vsrc, types[vsrc->type]);
|
||||
|
||||
if (pdfdst == pdfsrc && vsrc->type != PDFIO_VALTYPE_BINARY)
|
||||
{
|
||||
@@ -76,8 +76,7 @@ _pdfioValueCopy(pdfio_file_t *pdfdst, // I - Destination PDF file
|
||||
return (NULL);
|
||||
|
||||
case PDFIO_VALTYPE_ARRAY :
|
||||
if ((vdst->value.array = pdfioArrayCopy(pdfdst, vsrc->value.array)) == NULL)
|
||||
return (NULL);
|
||||
vdst->value.array = pdfioArrayCopy(pdfdst, vsrc->value.array);
|
||||
break;
|
||||
|
||||
case PDFIO_VALTYPE_BINARY :
|
||||
@@ -98,14 +97,12 @@ _pdfioValueCopy(pdfio_file_t *pdfdst, // I - Destination PDF file
|
||||
return (vdst);
|
||||
|
||||
case PDFIO_VALTYPE_DICT :
|
||||
if ((vdst->value.dict = pdfioDictCopy(pdfdst, vsrc->value.dict)) == NULL)
|
||||
return (NULL);
|
||||
vdst->value.dict = pdfioDictCopy(pdfdst, vsrc->value.dict);
|
||||
break;
|
||||
|
||||
case PDFIO_VALTYPE_NAME :
|
||||
case PDFIO_VALTYPE_STRING :
|
||||
if ((vdst->value.name = pdfioStringCreate(pdfdst, vsrc->value.name)) == NULL)
|
||||
return (NULL);
|
||||
vdst->value.name = pdfioStringCreate(pdfdst, vsrc->value.name);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -160,7 +157,7 @@ _pdfioValueDecrypt(pdfio_file_t *pdf, // I - PDF file
|
||||
_pdfioFileError(pdf, "Unable to read encrypted binary string - too long.");
|
||||
return (false);
|
||||
}
|
||||
else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(pdf, /*bptr*/NULL)) == NULL)
|
||||
else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(pdf)) == NULL)
|
||||
{
|
||||
_pdfioFileError(pdf, "Unable to read encrypted binary string - out of memory.");
|
||||
return (false);
|
||||
@@ -191,7 +188,7 @@ _pdfioValueDecrypt(pdfio_file_t *pdf, // I - PDF file
|
||||
_pdfioFileError(pdf, "Unable to read encrypted string - too long.");
|
||||
return (false);
|
||||
}
|
||||
else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(pdf, /*bptr*/NULL)) == NULL)
|
||||
else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(pdf)) == NULL)
|
||||
{
|
||||
_pdfioFileError(pdf, "Unable to read encrypted binary string - out of memory.");
|
||||
return (false);
|
||||
@@ -341,7 +338,7 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
|
||||
size_t depth) // I - Depth of value
|
||||
{
|
||||
_pdfio_value_t *ret = NULL; // Return value
|
||||
char *token = _pdfioStringAllocBuffer(pdf, /*bptr*/NULL);
|
||||
char *token = _pdfioStringAllocBuffer(pdf);
|
||||
// Token buffer
|
||||
time_t timeval; // Date/time value
|
||||
#ifdef DEBUG
|
||||
@@ -362,7 +359,7 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
|
||||
#endif // DEBUG
|
||||
|
||||
|
||||
PDFIO_DEBUG("_pdfioValueRead(pdf=%p, obj=%p, v=%p)\n", (void *)pdf, (void *)obj, (void *)v);
|
||||
PDFIO_DEBUG("_pdfioValueRead(pdf=%p, obj=%p, v=%p)\n", pdf, obj, v);
|
||||
|
||||
if (!token)
|
||||
goto done;
|
||||
@@ -518,7 +515,7 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
|
||||
// Integer...
|
||||
long generation = 0; // Generation number
|
||||
|
||||
while (tempptr < tb->bufend && generation < 65536 && isdigit(*tempptr & 255))
|
||||
while (tempptr < tb->bufend && isdigit(*tempptr & 255))
|
||||
{
|
||||
generation = generation * 10 + *tempptr - '0';
|
||||
tempptr ++;
|
||||
@@ -603,12 +600,10 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
_pdfioValueWrite(
|
||||
_pdfio_printf_t cb, // I - Printf callback function
|
||||
void *cbdata, // I - Printf callback data
|
||||
pdfio_obj_t *obj, // I - Object, if any
|
||||
_pdfio_value_t *v, // I - Value
|
||||
off_t *length) // O - Offset to /Length value, if any
|
||||
_pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file
|
||||
pdfio_obj_t *obj, // I - Object, if any
|
||||
_pdfio_value_t *v, // I - Value
|
||||
off_t *length)// O - Offset to /Length value, if any
|
||||
{
|
||||
switch (v->type)
|
||||
{
|
||||
@@ -616,7 +611,7 @@ _pdfioValueWrite(
|
||||
return (false);
|
||||
|
||||
case PDFIO_VALTYPE_ARRAY :
|
||||
return (_pdfioArrayWrite(cb, cbdata, obj, v->value.array));
|
||||
return (_pdfioArrayWrite(v->value.array, obj));
|
||||
|
||||
case PDFIO_VALTYPE_BINARY :
|
||||
{
|
||||
@@ -626,26 +621,26 @@ _pdfioValueWrite(
|
||||
bool ret = false; // Return value
|
||||
|
||||
|
||||
if (obj && obj->pdf->encryption)
|
||||
if (obj && pdf->encryption)
|
||||
{
|
||||
// Write encrypted string...
|
||||
_pdfio_crypto_ctx_t ctx; // Encryption context
|
||||
_pdfio_crypto_cb_t ccb; // Encryption callback
|
||||
_pdfio_crypto_cb_t cb; // Encryption callback
|
||||
size_t ivlen; // Number of initialization vector bytes
|
||||
|
||||
if (v->value.binary.datalen > PDFIO_MAX_STRING)
|
||||
{
|
||||
_pdfioFileError(obj->pdf, "Unable to write encrypted binary string - too long.");
|
||||
_pdfioFileError(pdf, "Unable to write encrypted binary string - too long.");
|
||||
return (false);
|
||||
}
|
||||
else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(obj->pdf, /*bptr*/NULL)) == NULL)
|
||||
else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(pdf)) == NULL)
|
||||
{
|
||||
_pdfioFileError(obj->pdf, "Unable to write encrypted binary string - out of memory.");
|
||||
_pdfioFileError(pdf, "Unable to write encrypted binary string - out of memory.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
ccb = _pdfioCryptoMakeWriter(obj->pdf, obj, &ctx, temp, &ivlen);
|
||||
databytes = (ccb)(&ctx, temp + ivlen, v->value.binary.data, v->value.binary.datalen) + ivlen;
|
||||
cb = _pdfioCryptoMakeWriter(pdf, obj, &ctx, temp, &ivlen);
|
||||
databytes = (cb)(&ctx, temp + ivlen, v->value.binary.data, v->value.binary.datalen) + ivlen;
|
||||
dataptr = temp;
|
||||
}
|
||||
else
|
||||
@@ -654,33 +649,33 @@ _pdfioValueWrite(
|
||||
databytes = v->value.binary.datalen;
|
||||
}
|
||||
|
||||
if (!(cb)(cbdata, "<"))
|
||||
if (!_pdfioFilePuts(pdf, "<"))
|
||||
goto bindone;
|
||||
|
||||
for (; databytes > 1; databytes -= 2, dataptr += 2)
|
||||
{
|
||||
if (!(cb)(cbdata, "%02X%02X", dataptr[0], dataptr[1]))
|
||||
if (!_pdfioFilePrintf(pdf, "%02X%02X", dataptr[0], dataptr[1]))
|
||||
goto bindone;
|
||||
}
|
||||
|
||||
if (databytes > 0 && !(cb)(cbdata, "%02X", dataptr[0]))
|
||||
if (databytes > 0 && !_pdfioFilePrintf(pdf, "%02X", dataptr[0]))
|
||||
goto bindone;
|
||||
|
||||
ret = (cb)(cbdata, ">");
|
||||
ret = _pdfioFilePuts(pdf, ">");
|
||||
|
||||
bindone:
|
||||
|
||||
if (temp)
|
||||
_pdfioStringFreeBuffer(obj->pdf, (char *)temp);
|
||||
_pdfioStringFreeBuffer(pdf, (char *)temp);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
case PDFIO_VALTYPE_BOOLEAN :
|
||||
if (v->value.boolean)
|
||||
return ((cb)(cbdata, " true"));
|
||||
return (_pdfioFilePuts(pdf, " true"));
|
||||
else
|
||||
return ((cb)(cbdata, " false"));
|
||||
return (_pdfioFilePuts(pdf, " false"));
|
||||
|
||||
case PDFIO_VALTYPE_DATE :
|
||||
{
|
||||
@@ -695,64 +690,64 @@ _pdfioValueWrite(
|
||||
|
||||
snprintf(datestr, sizeof(datestr), "D:%04d%02d%02d%02d%02d%02dZ", date.tm_year + 1900, date.tm_mon + 1, date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec);
|
||||
|
||||
if (obj && obj->pdf->encryption)
|
||||
if (obj && pdf->encryption)
|
||||
{
|
||||
// Write encrypted string...
|
||||
uint8_t temp[64], // Encrypted bytes
|
||||
*tempptr; // Pointer into encrypted bytes
|
||||
_pdfio_crypto_ctx_t ctx; // Encryption context
|
||||
_pdfio_crypto_cb_t ccb; // Encryption callback
|
||||
_pdfio_crypto_cb_t cb; // Encryption callback
|
||||
size_t len = strlen(datestr),
|
||||
// Length of value
|
||||
ivlen, // Number of initialization vector bytes
|
||||
tempbytes; // Number of output bytes
|
||||
|
||||
ccb = _pdfioCryptoMakeWriter(obj->pdf, obj, &ctx, temp, &ivlen);
|
||||
tempbytes = (ccb)(&ctx, temp + ivlen, (const uint8_t *)datestr, len) + ivlen;
|
||||
cb = _pdfioCryptoMakeWriter(pdf, obj, &ctx, temp, &ivlen);
|
||||
tempbytes = (cb)(&ctx, temp + ivlen, (const uint8_t *)datestr, len) + ivlen;
|
||||
|
||||
if (!(cb)(cbdata, "<"))
|
||||
if (!_pdfioFilePuts(pdf, "<"))
|
||||
return (false);
|
||||
|
||||
for (tempptr = temp; tempbytes > 1; tempbytes -= 2, tempptr += 2)
|
||||
{
|
||||
if (!(cb)(cbdata, "%02X%02X", tempptr[0], tempptr[1]))
|
||||
if (!_pdfioFilePrintf(pdf, "%02X%02X", tempptr[0], tempptr[1]))
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (tempbytes > 0)
|
||||
return ((cb)(cbdata, "%02X>", *tempptr));
|
||||
return (_pdfioFilePrintf(pdf, "%02X>", *tempptr));
|
||||
else
|
||||
return ((cb)(cbdata, ">"));
|
||||
return (_pdfioFilePuts(pdf, ">"));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ((cb)(cbdata, "%S", datestr));
|
||||
return (_pdfioFilePrintf(pdf, "%S", datestr));
|
||||
}
|
||||
}
|
||||
|
||||
case PDFIO_VALTYPE_DICT :
|
||||
return (_pdfioDictWrite(cb, cbdata, obj, v->value.dict, length));
|
||||
return (_pdfioDictWrite(v->value.dict, obj, length));
|
||||
|
||||
case PDFIO_VALTYPE_INDIRECT :
|
||||
return ((cb)(cbdata, " %lu %u R", (unsigned long)v->value.indirect.number, v->value.indirect.generation));
|
||||
return (_pdfioFilePrintf(pdf, " %lu %u R", (unsigned long)v->value.indirect.number, v->value.indirect.generation));
|
||||
|
||||
case PDFIO_VALTYPE_NAME :
|
||||
return ((cb)(cbdata, "%N", v->value.name));
|
||||
return (_pdfioFilePrintf(pdf, "%N", v->value.name));
|
||||
|
||||
case PDFIO_VALTYPE_NULL :
|
||||
return ((cb)(cbdata, " null"));
|
||||
return (_pdfioFilePuts(pdf, " null"));
|
||||
|
||||
case PDFIO_VALTYPE_NUMBER :
|
||||
return ((cb)(cbdata, " %.6f", v->value.number));
|
||||
return (_pdfioFilePrintf(pdf, " %.6f", v->value.number));
|
||||
|
||||
case PDFIO_VALTYPE_STRING :
|
||||
if (obj && obj->pdf->encryption)
|
||||
if (obj && pdf->encryption)
|
||||
{
|
||||
// Write encrypted string...
|
||||
uint8_t *temp = NULL, // Encrypted bytes
|
||||
*tempptr; // Pointer into encrypted bytes
|
||||
_pdfio_crypto_ctx_t ctx; // Encryption context
|
||||
_pdfio_crypto_cb_t ccb; // Encryption callback
|
||||
_pdfio_crypto_cb_t cb; // Encryption callback
|
||||
size_t len = strlen(v->value.string),
|
||||
// Length of value
|
||||
ivlen, // Number of initialization vector bytes
|
||||
@@ -761,42 +756,42 @@ _pdfioValueWrite(
|
||||
|
||||
if (len > PDFIO_MAX_STRING)
|
||||
{
|
||||
_pdfioFileError(obj->pdf, "Unable to write encrypted string - too long.");
|
||||
_pdfioFileError(pdf, "Unable to write encrypted string - too long.");
|
||||
return (false);
|
||||
}
|
||||
else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(obj->pdf, /*bptr*/NULL)) == NULL)
|
||||
else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(pdf)) == NULL)
|
||||
{
|
||||
_pdfioFileError(obj->pdf, "Unable to write encrypted string - out of memory.");
|
||||
_pdfioFileError(pdf, "Unable to write encrypted string - out of memory.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
ccb = _pdfioCryptoMakeWriter(obj->pdf, obj, &ctx, temp, &ivlen);
|
||||
tempbytes = (ccb)(&ctx, temp + ivlen, (const uint8_t *)v->value.string, len) + ivlen;
|
||||
cb = _pdfioCryptoMakeWriter(pdf, obj, &ctx, temp, &ivlen);
|
||||
tempbytes = (cb)(&ctx, temp + ivlen, (const uint8_t *)v->value.string, len) + ivlen;
|
||||
|
||||
if (!(cb)(cbdata, "<"))
|
||||
if (!_pdfioFilePuts(pdf, "<"))
|
||||
goto strdone;
|
||||
|
||||
for (tempptr = temp; tempbytes > 1; tempbytes -= 2, tempptr += 2)
|
||||
{
|
||||
if (!(cb)(cbdata, "%02X%02X", tempptr[0], tempptr[1]))
|
||||
if (!_pdfioFilePrintf(pdf, "%02X%02X", tempptr[0], tempptr[1]))
|
||||
goto strdone;
|
||||
}
|
||||
|
||||
if (tempbytes > 0 && !(cb)(cbdata, "%02X", *tempptr))
|
||||
if (tempbytes > 0 && !_pdfioFilePrintf(pdf, "%02X", *tempptr))
|
||||
goto strdone;
|
||||
|
||||
ret = (cb)(cbdata, ">");
|
||||
ret = _pdfioFilePuts(pdf, ">");
|
||||
|
||||
strdone :
|
||||
|
||||
_pdfioStringFreeBuffer(obj->pdf, (char *)temp);
|
||||
_pdfioStringFreeBuffer(pdf, (char *)temp);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write unencrypted string...
|
||||
return ((cb)(cbdata, "%S", v->value.string));
|
||||
return (_pdfioFilePrintf(pdf, "%S", v->value.string));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
22
pdfio.h
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// Public header file for PDFio.
|
||||
//
|
||||
// Copyright © 2021-2026 by Michael R Sweet.
|
||||
// Copyright © 2021-2025 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@@ -23,9 +23,9 @@ extern "C" {
|
||||
// Version numbers...
|
||||
//
|
||||
|
||||
# define PDFIO_VERSION "1.7.0"
|
||||
# define PDFIO_VERSION "1.5.3"
|
||||
# define PDFIO_VERSION_MAJOR 1
|
||||
# define PDFIO_VERSION_MINOR 7
|
||||
# define PDFIO_VERSION_MINOR 5
|
||||
|
||||
|
||||
//
|
||||
@@ -72,11 +72,11 @@ typedef enum pdfio_filter_e // Compression/decompression filters for streams
|
||||
PDFIO_FILTER_NONE, // No filter
|
||||
PDFIO_FILTER_ASCIIHEX, // ASCIIHexDecode filter (reading only)
|
||||
PDFIO_FILTER_ASCII85, // ASCII85Decode filter (reading only)
|
||||
PDFIO_FILTER_CCITTFAX, // CCITTFaxDecode filter (reading only)
|
||||
PDFIO_FILTER_CCITTFAX, // CCITTFaxDecode filter
|
||||
PDFIO_FILTER_CRYPT, // Encryption filter
|
||||
PDFIO_FILTER_DCT, // DCTDecode (JPEG) filter
|
||||
PDFIO_FILTER_FLATE, // FlateDecode filter
|
||||
PDFIO_FILTER_JBIG2, // JBIG2Decode filter (reading only)
|
||||
PDFIO_FILTER_JBIG2, // JBIG2Decode filter
|
||||
PDFIO_FILTER_JPX, // JPXDecode filter (reading only)
|
||||
PDFIO_FILTER_LZW, // LZWDecode filter (reading only)
|
||||
PDFIO_FILTER_RUNLENGTH, // RunLengthDecode filter (reading only)
|
||||
@@ -201,7 +201,6 @@ extern time_t pdfioFileGetCreationDate(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||
extern const char *pdfioFileGetCreator(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||
extern pdfio_array_t *pdfioFileGetID(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||
extern const char *pdfioFileGetKeywords(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||
extern const char *pdfioFileGetLanguage(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||
extern time_t pdfioFileGetModificationDate(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||
extern const char *pdfioFileGetName(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||
extern size_t pdfioFileGetNumObjs(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||
@@ -218,7 +217,6 @@ extern void pdfioFileSetAuthor(pdfio_file_t *pdf, const char *value) _PDFIO_PUB
|
||||
extern void pdfioFileSetCreationDate(pdfio_file_t *pdf, time_t value) _PDFIO_PUBLIC;
|
||||
extern void pdfioFileSetCreator(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
|
||||
extern void pdfioFileSetKeywords(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
|
||||
extern void pdfioFileSetLanguage(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
|
||||
extern void pdfioFileSetModificationDate(pdfio_file_t *pdf, time_t value) _PDFIO_PUBLIC;
|
||||
extern bool pdfioFileSetPermissions(pdfio_file_t *pdf, pdfio_permission_t permissions, pdfio_encryption_t encryption, const char *owner_password, const char *user_password) _PDFIO_PUBLIC;
|
||||
extern void pdfioFileSetSubject(pdfio_file_t *pdf, const char *value) _PDFIO_PUBLIC;
|
||||
@@ -238,17 +236,7 @@ extern const char *pdfioObjGetType(pdfio_obj_t *obj) _PDFIO_PUBLIC;
|
||||
extern pdfio_stream_t *pdfioObjOpenStream(pdfio_obj_t *obj, bool decode) _PDFIO_PUBLIC;
|
||||
|
||||
extern bool pdfioPageCopy(pdfio_file_t *pdf, pdfio_obj_t *srcpage) _PDFIO_PUBLIC;
|
||||
extern pdfio_array_t *pdfioPageGetArray(pdfio_obj_t *page, const char *key) _PDFIO_PUBLIC;
|
||||
extern unsigned char *pdfioPageGetBinary(pdfio_obj_t *page, const char *key, size_t *length) _PDFIO_PUBLIC;
|
||||
extern bool pdfioPageGetBoolean(pdfio_obj_t *page, const char *key) _PDFIO_PUBLIC;
|
||||
extern time_t pdfioPageGetDate(pdfio_obj_t *page, const char *key) _PDFIO_PUBLIC;
|
||||
extern pdfio_dict_t *pdfioPageGetDict(pdfio_obj_t *page, const char *key) _PDFIO_PUBLIC;
|
||||
extern const char *pdfioPageGetName(pdfio_obj_t *page, const char *key) _PDFIO_PUBLIC;
|
||||
extern size_t pdfioPageGetNumStreams(pdfio_obj_t *page) _PDFIO_PUBLIC;
|
||||
extern double pdfioPageGetNumber(pdfio_obj_t *page, const char *key) _PDFIO_PUBLIC;
|
||||
extern pdfio_obj_t *pdfioPageGetObj(pdfio_obj_t *page, const char *key) _PDFIO_PUBLIC;
|
||||
extern pdfio_rect_t *pdfioPageGetRect(pdfio_obj_t *page, const char *key, pdfio_rect_t *rect) _PDFIO_PUBLIC;
|
||||
extern const char *pdfioPageGetString(pdfio_obj_t *page, const char *key) _PDFIO_PUBLIC;
|
||||
extern pdfio_stream_t *pdfioPageOpenStream(pdfio_obj_t *page, size_t n, bool decode) _PDFIO_PUBLIC;
|
||||
|
||||
extern bool pdfioStreamClose(pdfio_stream_t *st) _PDFIO_PUBLIC;
|
||||
|
||||
@@ -11,4 +11,3 @@ Cflags: @PKGCONFIG_CFLAGS@
|
||||
Libs: @PKGCONFIG_LIBS@
|
||||
Libs.private: @PKGCONFIG_LIBS_PRIVATE@
|
||||
Requires: @PKGCONFIG_REQUIRES@
|
||||
Requires.private: @PKGCONFIG_REQUIRES_PRIVATE@
|
||||
|
||||
@@ -87,7 +87,6 @@
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>ttf;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
@@ -102,7 +101,6 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>ttf;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
@@ -117,7 +115,6 @@
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>ttf;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>HAVE_LIBPNG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
@@ -133,7 +130,6 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>ttf;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>HAVE_LIBPNG;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
@@ -149,8 +145,7 @@
|
||||
<ClInclude Include="pdfio-content.h" />
|
||||
<ClInclude Include="pdfio-private.h" />
|
||||
<ClInclude Include="pdfio.h" />
|
||||
<ClInclude Include="ttf\ttf.h" />
|
||||
<ClInclude Include="ttf\ttf-private.h" />
|
||||
<ClInclude Include="ttf.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pdfio-aes.c" />
|
||||
@@ -160,7 +155,6 @@
|
||||
<ClCompile Include="pdfio-crypto.c" />
|
||||
<ClCompile Include="pdfio-dict.c" />
|
||||
<ClCompile Include="pdfio-file.c" />
|
||||
<ClCompile Include="pdfio-lzw.c" />
|
||||
<ClCompile Include="pdfio-md5.c" />
|
||||
<ClCompile Include="pdfio-object.c" />
|
||||
<ClCompile Include="pdfio-page.c" />
|
||||
@@ -170,8 +164,7 @@
|
||||
<ClCompile Include="pdfio-string.c" />
|
||||
<ClCompile Include="pdfio-token.c" />
|
||||
<ClCompile Include="pdfio-value.c" />
|
||||
<ClCompile Include="ttf\ttf-cache.c" />
|
||||
<ClCompile Include="ttf\ttf-file.c" />
|
||||
<ClCompile Include="ttf.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
||||
@@ -22,11 +22,8 @@
|
||||
273440CD263D727800FBFD63 /* pdfio-page.c in Sources */ = {isa = PBXBuildFile; fileRef = 273440C2263D727800FBFD63 /* pdfio-page.c */; };
|
||||
273440D8263D72E100FBFD63 /* testpdfio.c in Sources */ = {isa = PBXBuildFile; fileRef = 273440D7263D72E100FBFD63 /* testpdfio.c */; };
|
||||
273440E4263DD7EA00FBFD63 /* pdfio-token.c in Sources */ = {isa = PBXBuildFile; fileRef = 273440E3263DD7EA00FBFD63 /* pdfio-token.c */; };
|
||||
273707A52F299C3100953C95 /* pdfio-lzw.c in Sources */ = {isa = PBXBuildFile; fileRef = 273707A42F299C3100953C95 /* pdfio-lzw.c */; };
|
||||
2741C9A22F05872C002D93F2 /* ttf-cache.c in Sources */ = {isa = PBXBuildFile; fileRef = 2741C99F2F05872C002D93F2 /* ttf-cache.c */; };
|
||||
2741C9A32F05872C002D93F2 /* ttf-file.c in Sources */ = {isa = PBXBuildFile; fileRef = 2741C9A02F05872C002D93F2 /* ttf-file.c */; };
|
||||
2741C9A42F05872C002D93F2 /* ttf-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 2741C9A12F05872C002D93F2 /* ttf-private.h */; };
|
||||
2741C9A52F05872C002D93F2 /* ttf.h in Headers */ = {isa = PBXBuildFile; fileRef = 2741C99E2F05872C002D93F2 /* ttf.h */; };
|
||||
279E1035267D043B00D3A349 /* ttf.h in Headers */ = {isa = PBXBuildFile; fileRef = 279E1033267D043B00D3A349 /* ttf.h */; };
|
||||
279E1036267D043B00D3A349 /* ttf.c in Sources */ = {isa = PBXBuildFile; fileRef = 279E1034267D043B00D3A349 /* ttf.c */; };
|
||||
279E103B267D04E600D3A349 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 279E103A267D04E600D3A349 /* libz.tbd */; };
|
||||
27CF90442711DFFE00E50FE4 /* pdfio-aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 27CF90432711DFFE00E50FE4 /* pdfio-aes.c */; };
|
||||
27ECBD8926419DAB0025312A /* libpdfio.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 273440B0263D6FE200FBFD63 /* libpdfio.a */; };
|
||||
@@ -85,11 +82,8 @@
|
||||
273440E1263D73A300FBFD63 /* pdfio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = pdfio.html; path = doc/pdfio.html; sourceTree = "<group>"; };
|
||||
273440E2263D73A300FBFD63 /* pdfio.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pdfio.3; path = doc/pdfio.3; sourceTree = "<group>"; };
|
||||
273440E3263DD7EA00FBFD63 /* pdfio-token.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "pdfio-token.c"; sourceTree = "<group>"; };
|
||||
273707A42F299C3100953C95 /* pdfio-lzw.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "pdfio-lzw.c"; sourceTree = "<group>"; };
|
||||
2741C99E2F05872C002D93F2 /* ttf.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ttf.h; path = ttf/ttf.h; sourceTree = "<group>"; };
|
||||
2741C99F2F05872C002D93F2 /* ttf-cache.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "ttf-cache.c"; path = "ttf/ttf-cache.c"; sourceTree = "<group>"; };
|
||||
2741C9A02F05872C002D93F2 /* ttf-file.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "ttf-file.c"; path = "ttf/ttf-file.c"; sourceTree = "<group>"; };
|
||||
2741C9A12F05872C002D93F2 /* ttf-private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "ttf-private.h"; path = "ttf/ttf-private.h"; sourceTree = "<group>"; };
|
||||
279E1033267D043B00D3A349 /* ttf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ttf.h; sourceTree = "<group>"; };
|
||||
279E1034267D043B00D3A349 /* ttf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ttf.c; sourceTree = "<group>"; };
|
||||
279E103A267D04E600D3A349 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
27CF90432711DFFE00E50FE4 /* pdfio-aes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "pdfio-aes.c"; sourceTree = "<group>"; };
|
||||
27F2F05D2710BE92008ECD36 /* pdfio-md5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "pdfio-md5.c"; sourceTree = "<group>"; };
|
||||
@@ -176,7 +170,6 @@
|
||||
27F2F05F2710BE92008ECD36 /* pdfio-crypto.c */,
|
||||
273440BE263D727800FBFD63 /* pdfio-dict.c */,
|
||||
273440BD263D727800FBFD63 /* pdfio-file.c */,
|
||||
273707A42F299C3100953C95 /* pdfio-lzw.c */,
|
||||
27F2F05D2710BE92008ECD36 /* pdfio-md5.c */,
|
||||
273440BC263D727800FBFD63 /* pdfio-object.c */,
|
||||
273440C2263D727800FBFD63 /* pdfio-page.c */,
|
||||
@@ -186,10 +179,8 @@
|
||||
273440B9263D727800FBFD63 /* pdfio-string.c */,
|
||||
273440E3263DD7EA00FBFD63 /* pdfio-token.c */,
|
||||
273440C0263D727800FBFD63 /* pdfio-value.c */,
|
||||
2741C99E2F05872C002D93F2 /* ttf.h */,
|
||||
2741C99F2F05872C002D93F2 /* ttf-cache.c */,
|
||||
2741C9A02F05872C002D93F2 /* ttf-file.c */,
|
||||
2741C9A12F05872C002D93F2 /* ttf-private.h */,
|
||||
279E1034267D043B00D3A349 /* ttf.c */,
|
||||
279E1033267D043B00D3A349 /* ttf.h */,
|
||||
);
|
||||
name = Library;
|
||||
sourceTree = "<group>";
|
||||
@@ -218,11 +209,10 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
27FCBDE42D19F9B300485EEE /* pdfio-base-font-widths.h in Headers */,
|
||||
2741C9A42F05872C002D93F2 /* ttf-private.h in Headers */,
|
||||
2741C9A52F05872C002D93F2 /* ttf.h in Headers */,
|
||||
273440CC263D727800FBFD63 /* pdfio.h in Headers */,
|
||||
271EA706265B2B1000ACDD39 /* pdfio-content.h in Headers */,
|
||||
273440C3263D727800FBFD63 /* pdfio-private.h in Headers */,
|
||||
279E1035267D043B00D3A349 /* ttf.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -271,7 +261,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 2600;
|
||||
LastUpgradeCheck = 1600;
|
||||
TargetAttributes = {
|
||||
273440AF263D6FE200FBFD63 = {
|
||||
CreatedOnToolsVersion = 12.5;
|
||||
@@ -305,16 +295,14 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
279E1036267D043B00D3A349 /* ttf.c in Sources */,
|
||||
273440C9263D727800FBFD63 /* pdfio-dict.c in Sources */,
|
||||
273440C8263D727800FBFD63 /* pdfio-file.c in Sources */,
|
||||
273440CB263D727800FBFD63 /* pdfio-value.c in Sources */,
|
||||
273707A52F299C3100953C95 /* pdfio-lzw.c in Sources */,
|
||||
273440CA263D727800FBFD63 /* pdfio-stream.c in Sources */,
|
||||
273440CD263D727800FBFD63 /* pdfio-page.c in Sources */,
|
||||
27F2F0622710BE92008ECD36 /* pdfio-crypto.c in Sources */,
|
||||
27F2F0642711243D008ECD36 /* pdfio-sha256.c in Sources */,
|
||||
2741C9A22F05872C002D93F2 /* ttf-cache.c in Sources */,
|
||||
2741C9A32F05872C002D93F2 /* ttf-file.c in Sources */,
|
||||
273440C5263D727800FBFD63 /* pdfio-array.c in Sources */,
|
||||
273440E4263DD7EA00FBFD63 /* pdfio-token.c in Sources */,
|
||||
273440C7263D727800FBFD63 /* pdfio-object.c in Sources */,
|
||||
@@ -365,14 +353,12 @@
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_COMPLETION_HANDLER_MISUSE = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_IMPLICIT_FALLTHROUGH = NO;
|
||||
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
@@ -391,7 +377,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1.6.1;
|
||||
CURRENT_PROJECT_VERSION = 1.1.2;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@@ -402,16 +388,10 @@
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
"DEBUG=1",
|
||||
"HAVE_LIBPNG=1",
|
||||
"HAVE_TM_GMTOFF=1",
|
||||
"HAVE_TIMEGM=1",
|
||||
);
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
|
||||
@@ -419,29 +399,16 @@
|
||||
GCC_WARN_SIGN_COMPARE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNKNOWN_PRAGMAS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_LABEL = YES;
|
||||
GCC_WARN_UNUSED_PARAMETER = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
/usr/local/include,
|
||||
/opt/local/include,
|
||||
/opt/homebrew/include,
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_LDFLAGS = (
|
||||
"-L/usr/local/lib",
|
||||
"-L/opt/local/lib",
|
||||
"-L/opt/homebrew/lib",
|
||||
"-lpng16",
|
||||
);
|
||||
RUN_CLANG_STATIC_ANALYZER = YES;
|
||||
SDKROOT = macosx;
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
@@ -465,14 +432,12 @@
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_COMPLETION_HANDLER_MISUSE = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_IMPLICIT_FALLTHROUGH = NO;
|
||||
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
@@ -491,7 +456,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1.6.1;
|
||||
CURRENT_PROJECT_VERSION = 1.1.2;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
@@ -500,17 +465,10 @@
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
"HAVE_LIBPNG=1",
|
||||
"HAVE_TM_GMTOFF=1",
|
||||
"HAVE_TIMEGM=1",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
|
||||
@@ -518,28 +476,15 @@
|
||||
GCC_WARN_SIGN_COMPARE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNKNOWN_PRAGMAS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_LABEL = YES;
|
||||
GCC_WARN_UNUSED_PARAMETER = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
/usr/local/include,
|
||||
/opt/local/include,
|
||||
/opt/homebrew/include,
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
OTHER_LDFLAGS = (
|
||||
"-L/usr/local/lib",
|
||||
"-L/opt/local/lib",
|
||||
"-L/opt/homebrew/lib",
|
||||
"-lpng16",
|
||||
);
|
||||
RUN_CLANG_STATIC_ANALYZER = YES;
|
||||
SDKROOT = macosx;
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
|
||||
83
pdfio1.def
@@ -1,23 +1,9 @@
|
||||
LIBRARY pdfio1
|
||||
VERSION 1.7
|
||||
VERSION 1.5
|
||||
EXPORTS
|
||||
_pdfio_strlcpy
|
||||
_pdfio_strtod
|
||||
_pdfio_utf16cpy
|
||||
_pdfio_vsnprintf
|
||||
_pdfioArrayDebug
|
||||
_pdfioArrayDecrypt
|
||||
_pdfioArrayDelete
|
||||
_pdfioArrayGetValue
|
||||
_pdfioArrayRead
|
||||
_pdfioArrayWrite
|
||||
_pdfioCryptoAESDecrypt
|
||||
_pdfioCryptoAESEncrypt
|
||||
_pdfioCryptoAESInit
|
||||
_pdfioCryptoLock
|
||||
_pdfioCryptoMakeRandom
|
||||
_pdfioCryptoMakeReader
|
||||
_pdfioCryptoMakeWriter
|
||||
_pdfioCryptoMD5Append
|
||||
_pdfioCryptoMD5Finish
|
||||
_pdfioCryptoMD5Init
|
||||
@@ -26,56 +12,9 @@ _pdfioCryptoRC4Init
|
||||
_pdfioCryptoSHA256Append
|
||||
_pdfioCryptoSHA256Finish
|
||||
_pdfioCryptoSHA256Init
|
||||
_pdfioCryptoUnlock
|
||||
_pdfioDictDebug
|
||||
_pdfioDictDecrypt
|
||||
_pdfioDictDelete
|
||||
_pdfioDictGetValue
|
||||
_pdfioDictRead
|
||||
_pdfioDictSetValue
|
||||
_pdfioDictWrite
|
||||
_pdfioFileAddMappedObj
|
||||
_pdfioFileAddPage
|
||||
_pdfioFileConsume
|
||||
_pdfioFileCreateObj
|
||||
_pdfioFileDefaultError
|
||||
_pdfioFileError
|
||||
_pdfioFileFindMappedObj
|
||||
_pdfioFileFlush
|
||||
_pdfioFileGetChar
|
||||
_pdfioFileGets
|
||||
_pdfioFilePeek
|
||||
_pdfioFilePrintf
|
||||
_pdfioFilePuts
|
||||
_pdfioFileRead
|
||||
_pdfioFileSeek
|
||||
_pdfioFileTell
|
||||
_pdfioFileWrite
|
||||
_pdfioLZWCreate
|
||||
_pdfioLZWDelete
|
||||
_pdfioLZWInflate
|
||||
_pdfioObjDelete
|
||||
_pdfioObjGetExtension
|
||||
_pdfioObjLoad
|
||||
_pdfioObjSetExtension
|
||||
_pdfioObjWriteHeader
|
||||
_pdfioStreamCreate
|
||||
_pdfioStreamOpen
|
||||
_pdfioStringAllocBuffer
|
||||
_pdfioStringFreeBuffer
|
||||
_pdfioStringIsAllocated
|
||||
_pdfioTokenClear
|
||||
_pdfioTokenFlush
|
||||
_pdfioTokenGet
|
||||
_pdfioTokenInit
|
||||
_pdfioTokenPush
|
||||
_pdfioTokenRead
|
||||
_pdfioValueCopy
|
||||
_pdfioValueDebug
|
||||
_pdfioValueDecrypt
|
||||
_pdfioValueDelete
|
||||
_pdfioValueRead
|
||||
_pdfioValueWrite
|
||||
pdfioArrayAppendArray
|
||||
pdfioArrayAppendBinary
|
||||
pdfioArrayAppendBoolean
|
||||
@@ -104,10 +43,8 @@ pdfioArrayGetSize
|
||||
pdfioArrayGetString
|
||||
pdfioArrayGetType
|
||||
pdfioArrayRemove
|
||||
pdfioContentBeginMarked
|
||||
pdfioContentClip
|
||||
pdfioContentDrawImage
|
||||
pdfioContentEndMarked
|
||||
pdfioContentFill
|
||||
pdfioContentFillAndStroke
|
||||
pdfioContentMatrixConcat
|
||||
@@ -161,8 +98,8 @@ pdfioContentTextNewLineShow
|
||||
pdfioContentTextNewLineShowf
|
||||
pdfioContentTextNextLine
|
||||
pdfioContentTextShow
|
||||
pdfioContentTextShowf
|
||||
pdfioContentTextShowJustified
|
||||
pdfioContentTextShowf
|
||||
pdfioDictClear
|
||||
pdfioDictCopy
|
||||
pdfioDictCreate
|
||||
@@ -173,8 +110,8 @@ pdfioDictGetDate
|
||||
pdfioDictGetDict
|
||||
pdfioDictGetKey
|
||||
pdfioDictGetName
|
||||
pdfioDictGetNumber
|
||||
pdfioDictGetNumPairs
|
||||
pdfioDictGetNumber
|
||||
pdfioDictGetObj
|
||||
pdfioDictGetRect
|
||||
pdfioDictGetString
|
||||
@@ -192,12 +129,10 @@ pdfioDictSetObj
|
||||
pdfioDictSetRect
|
||||
pdfioDictSetString
|
||||
pdfioDictSetStringf
|
||||
pdfioFileAddOutputIntent
|
||||
pdfioFileClose
|
||||
pdfioFileCreate
|
||||
pdfioFileCreateArrayObj
|
||||
pdfioFileCreateFontObjFromBase
|
||||
pdfioFileCreateFontObjFromData
|
||||
pdfioFileCreateFontObjFromFile
|
||||
pdfioFileCreateICCObjFromData
|
||||
pdfioFileCreateICCObjFromFile
|
||||
@@ -217,7 +152,6 @@ pdfioFileGetCreationDate
|
||||
pdfioFileGetCreator
|
||||
pdfioFileGetID
|
||||
pdfioFileGetKeywords
|
||||
pdfioFileGetLanguage
|
||||
pdfioFileGetModificationDate
|
||||
pdfioFileGetName
|
||||
pdfioFileGetNumObjs
|
||||
@@ -234,7 +168,6 @@ pdfioFileSetAuthor
|
||||
pdfioFileSetCreationDate
|
||||
pdfioFileSetCreator
|
||||
pdfioFileSetKeywords
|
||||
pdfioFileSetLanguage
|
||||
pdfioFileSetModificationDate
|
||||
pdfioFileSetPermissions
|
||||
pdfioFileSetSubject
|
||||
@@ -258,17 +191,7 @@ pdfioPageCopy
|
||||
pdfioPageDictAddColorSpace
|
||||
pdfioPageDictAddFont
|
||||
pdfioPageDictAddImage
|
||||
pdfioPageGetArray
|
||||
pdfioPageGetBinary
|
||||
pdfioPageGetBoolean
|
||||
pdfioPageGetDate
|
||||
pdfioPageGetDict
|
||||
pdfioPageGetName
|
||||
pdfioPageGetNumber
|
||||
pdfioPageGetNumStreams
|
||||
pdfioPageGetObj
|
||||
pdfioPageGetRect
|
||||
pdfioPageGetString
|
||||
pdfioPageOpenStream
|
||||
pdfioStreamClose
|
||||
pdfioStreamConsume
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<metadata>
|
||||
<id>pdfio_native</id>
|
||||
<title>PDFio Library for VS2019+</title>
|
||||
<version>1.7.0</version>
|
||||
<version>1.5.3</version>
|
||||
<authors>Michael R Sweet</authors>
|
||||
<owners>michaelrsweet</owners>
|
||||
<projectUrl>https://github.com/michaelrsweet/pappl</projectUrl>
|
||||
@@ -16,7 +16,7 @@
|
||||
<copyright>Copyright © 2019-2025 by Michael R Sweet</copyright>
|
||||
<tags>pdf file native</tags>
|
||||
<dependencies>
|
||||
<dependency id="pdfio_native.redist" version="1.7.0" />
|
||||
<dependency id="pdfio_native.redist" version="1.5.3" />
|
||||
<dependency id="libpng_native.redist" version="1.6.30" />
|
||||
<dependency id="zlib_native.redist" version="1.2.11" />
|
||||
</dependencies>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<metadata>
|
||||
<id>pdfio_native.redist</id>
|
||||
<title>PDFio Library for VS2019+</title>
|
||||
<version>1.7.0</version>
|
||||
<version>1.5.3</version>
|
||||
<authors>Michael R Sweet</authors>
|
||||
<owners>michaelrsweet</owners>
|
||||
<projectUrl>https://github.com/michaelrsweet/pappl</projectUrl>
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Script to test PDFio against a directory of PDF files.
|
||||
#
|
||||
# Copyright © 2025-2026 by Michael R Sweet.
|
||||
#
|
||||
# Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
# information.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# ./test-corpus.sh DIRECTORY
|
||||
#
|
||||
|
||||
if test $# = 0; then
|
||||
echo "Usage: ./test-corpus.sh DIRECTORY"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
|
||||
ac_n=-n
|
||||
ac_c=
|
||||
else
|
||||
ac_n=
|
||||
ac_c='\c'
|
||||
fi
|
||||
|
||||
for file in $(find "$@" -name \*.pdf -print); do
|
||||
# Run testpdfio to test loading the file...
|
||||
echo $ac_n "\r$file: $ac_c"
|
||||
|
||||
./testpdfio --verbose $file >/dev/null 2>$file.log
|
||||
|
||||
if test $? = 0; then
|
||||
# Passed
|
||||
echo PASS
|
||||
rm -f $file.log
|
||||
else
|
||||
# Failed, preserve log and write to stdout...
|
||||
echo FAIL
|
||||
cat $file.log
|
||||
echo ""
|
||||
fi
|
||||
done
|
||||
292
test-internal.h
@@ -1,292 +0,0 @@
|
||||
//
|
||||
// Unit test header for C/C++ programs.
|
||||
//
|
||||
// Copyright © 2021-2025 by Michael R Sweet.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef TEST_H
|
||||
# define TEST_H
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <stdarg.h>
|
||||
# include <stdbool.h>
|
||||
# include <string.h>
|
||||
# if _WIN32
|
||||
# include <io.h>
|
||||
# define isatty(f) _isatty(f)
|
||||
# else
|
||||
# include <unistd.h>
|
||||
# endif // !_WIN32
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif // __cplusplus
|
||||
|
||||
|
||||
//
|
||||
// This header implements a simple unit test framework for C/C++ programs.
|
||||
// Inline functions are provided to write a test summary to stdout and the
|
||||
// details to stderr. This allows unit test programs to output a summary to
|
||||
// stdout with details sent to stderr, e.g.:
|
||||
//
|
||||
// mytestprogram 2>test.log
|
||||
//
|
||||
// Documentation:
|
||||
//
|
||||
// void testBegin(const char *title, ...)
|
||||
//
|
||||
// Start a test with a printf-style title message. "Title:" (the formatted
|
||||
// title followed by a colon) is output.
|
||||
//
|
||||
// void testEnd(bool pass)
|
||||
//
|
||||
// End a test without an additional message. "pass" should be `true` if the
|
||||
// test passed and `false` otherwise. "PASS" or "FAIL" is output.
|
||||
//
|
||||
// void testEndMessage(bool pass, const char *message, ...)
|
||||
//
|
||||
// End a test with an additional printf-style message. "pass" should be
|
||||
// `true` if the test passed and `false` otherwise. "PASS (message)" or
|
||||
// "FAIL (message)" is output.
|
||||
//
|
||||
// testError(const char *error, ...)
|
||||
//
|
||||
// Sends a formatted error string to stderr.
|
||||
//
|
||||
// testHexDump(const unsigned char *buffer, size_t bytes)
|
||||
//
|
||||
// Sends a hex dump of the specified buffer to stderr.
|
||||
//
|
||||
// testMessage(const char *error, ...)
|
||||
//
|
||||
// Outputs a formatted message string.
|
||||
//
|
||||
// testProgress(void)
|
||||
//
|
||||
// Shows a progress spinner for long-running tests.
|
||||
//
|
||||
// bool testsPassed
|
||||
//
|
||||
// This global variable specifies whether all tests have passed (`true`)
|
||||
// or one or more have failed (`false`).
|
||||
//
|
||||
|
||||
static bool testsPassed = true; // All tests passed?
|
||||
static int test_progress; // Current progress
|
||||
static char test_title[1024] = ""; // Current test title
|
||||
|
||||
|
||||
// Add printf syntax checking on supported compilers...
|
||||
#if defined(__has_extension) || defined(__GNUC__)
|
||||
# define TEST_FORMAT(a,b) __attribute__ ((__format__(__printf__,a,b)))
|
||||
static inline void testBegin(const char *title, ...) TEST_FORMAT(1,2);
|
||||
static inline void testEndMessage(bool pass, const char *message, ...) TEST_FORMAT(2,3);
|
||||
static inline void testError(const char *error, ...) TEST_FORMAT(1,2);
|
||||
static inline void testMessage(const char *error, ...) TEST_FORMAT(1,2);
|
||||
#endif // __has_extension || __GNUC__
|
||||
|
||||
|
||||
// Start a test
|
||||
static inline void
|
||||
testBegin(const char *title, ...) // I - printf-style title string
|
||||
{
|
||||
va_list ap; // Pointer to additional arguments
|
||||
|
||||
|
||||
// Format the title string
|
||||
va_start(ap, title);
|
||||
vsnprintf(test_title, sizeof(test_title), title, ap);
|
||||
va_end(ap);
|
||||
|
||||
// Send the title to stdout and stderr...
|
||||
test_progress = 0;
|
||||
|
||||
printf("%s: ", test_title);
|
||||
fflush(stdout);
|
||||
|
||||
if (!isatty(2))
|
||||
fprintf(stderr, "%s: ", test_title);
|
||||
}
|
||||
|
||||
|
||||
// End a test with no additional information
|
||||
static inline void
|
||||
testEnd(bool pass) // I - `true` if the test passed, `false` otherwise
|
||||
{
|
||||
// Send the test result to stdout and stderr
|
||||
if (test_progress)
|
||||
putchar('\b');
|
||||
|
||||
if (!pass)
|
||||
testsPassed = false;
|
||||
|
||||
puts(pass ? "PASS" : "FAIL");
|
||||
if (!isatty(2))
|
||||
fputs(pass ? "PASS\n" : "FAIL\n", stderr);
|
||||
|
||||
test_title[0] = '\0';
|
||||
}
|
||||
|
||||
|
||||
// End a test with no additional information
|
||||
static inline void
|
||||
testEndMessage(bool pass, // I - `true` if the test passed, `false` otherwise
|
||||
const char *message, ...)// I - printf-style message
|
||||
{
|
||||
char buffer[1024]; // Formatted title string
|
||||
va_list ap; // Pointer to additional arguments
|
||||
|
||||
|
||||
// Format the title string
|
||||
va_start(ap, message);
|
||||
vsnprintf(buffer, sizeof(buffer), message, ap);
|
||||
va_end(ap);
|
||||
|
||||
// Send the test result to stdout and stderr
|
||||
if (test_progress)
|
||||
putchar('\b');
|
||||
|
||||
printf(pass ? "PASS (%s)\n" : "FAIL (%s)\n", buffer);
|
||||
if (!isatty(2))
|
||||
fprintf(stderr, pass ? "PASS (%s)\n" : "FAIL (%s)\n", buffer);
|
||||
|
||||
test_title[0] = '\0';
|
||||
}
|
||||
|
||||
|
||||
// Show/update a progress spinner
|
||||
static inline void
|
||||
testProgress(void)
|
||||
{
|
||||
if (test_progress)
|
||||
putchar('\b');
|
||||
putchar("-\\|/"[test_progress & 3]);
|
||||
fflush(stdout);
|
||||
|
||||
test_progress ++;
|
||||
}
|
||||
|
||||
|
||||
// Show an error to stderr...
|
||||
static inline void
|
||||
testError(const char *error, ...) // I - printf-style error string
|
||||
{
|
||||
char buffer[1024]; // Formatted title string
|
||||
va_list ap; // Pointer to additional arguments
|
||||
|
||||
|
||||
// Format the error string
|
||||
va_start(ap, error);
|
||||
vsnprintf(buffer, sizeof(buffer), error, ap);
|
||||
va_end(ap);
|
||||
|
||||
// Send the error to stderr...
|
||||
fprintf(stderr, "%s\n", buffer);
|
||||
|
||||
if (test_title[0])
|
||||
fprintf(stderr, "%s: ", test_title);
|
||||
}
|
||||
|
||||
|
||||
// Show a message to stdout and stderr...
|
||||
static inline void
|
||||
testMessage(const char *error, ...) // I - printf-style error string
|
||||
{
|
||||
char buffer[1024]; // Formatted title string
|
||||
va_list ap; // Pointer to additional arguments
|
||||
|
||||
|
||||
// Format the error string
|
||||
va_start(ap, error);
|
||||
vsnprintf(buffer, sizeof(buffer), error, ap);
|
||||
va_end(ap);
|
||||
|
||||
// Send the message to stdout and stderr too if needed...
|
||||
printf("%s\n", buffer);
|
||||
if (test_title[0])
|
||||
{
|
||||
printf("%s: ", test_title);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
if (!isatty(2))
|
||||
{
|
||||
fprintf(stderr, "%s\n", buffer);
|
||||
|
||||
if (test_title[0])
|
||||
fprintf(stderr, "%s: ", test_title);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Show a hex dump of a buffer to stderr...
|
||||
static inline void
|
||||
testHexDump(const unsigned char *buffer,// I - Buffer
|
||||
size_t bytes) // I - Number of bytes
|
||||
{
|
||||
size_t i, j; // Looping vars
|
||||
int ch; // Current ASCII char
|
||||
|
||||
|
||||
if (test_title[0])
|
||||
fputs("\n", stderr);
|
||||
|
||||
// Show lines of 16 bytes at a time...
|
||||
for (i = 0; i < bytes; i += 16)
|
||||
{
|
||||
// Show the offset...
|
||||
fprintf(stderr, "%04x ", (unsigned)i);
|
||||
|
||||
// Then up to 16 bytes in hex...
|
||||
for (j = 0; j < 16; j ++)
|
||||
{
|
||||
if ((i + j) < bytes)
|
||||
fprintf(stderr, " %02x", buffer[i + j]);
|
||||
else
|
||||
fputs(" ", stderr);
|
||||
}
|
||||
|
||||
// Then the ASCII representation of the bytes...
|
||||
fputs(" ", stderr);
|
||||
|
||||
for (j = 0; j < 16 && (i + j) < bytes; j ++)
|
||||
{
|
||||
ch = buffer[i + j] & 127;
|
||||
|
||||
if (ch < ' ' || ch == 127)
|
||||
fputc('.', stderr);
|
||||
else
|
||||
fputc(ch, stderr);
|
||||
}
|
||||
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
if (test_title[0])
|
||||
fprintf(stderr, "%s: ", test_title);
|
||||
}
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif // __cplusplus
|
||||
#endif // !TEST_H
|
||||
@@ -1,5 +0,0 @@
|
||||
https://github.com/saucecontrol/Compact-ICC-Profiles
|
||||
|
||||
All profiles in this collection are released to the public domain under the
|
||||
Creative Commons CC0 license. They are free from restrictions on distribution
|
||||
and use to the extent allowed by law.
|
||||
|
Before Width: | Height: | Size: 245 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 9.5 KiB |
2815
testpdfio.c
305
testttf.c
Normal file
@@ -0,0 +1,305 @@
|
||||
//
|
||||
// Unit test program for TTF library
|
||||
//
|
||||
// https://github.com/michaelrsweet/ttf
|
||||
//
|
||||
// Copyright © 2018-2024 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// ./testttf [FILENAME]
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include "ttf.h"
|
||||
|
||||
|
||||
//
|
||||
// Local functions...
|
||||
//
|
||||
|
||||
static void error_cb(void *data, const char *message);
|
||||
static int test_font(const char *filename);
|
||||
|
||||
|
||||
//
|
||||
// 'main()' - Main entry for unit tests.
|
||||
//
|
||||
|
||||
int // O - Exit status
|
||||
main(int argc, // I - Number of command-line arguments
|
||||
char *argv[]) // I - Command-line arguments
|
||||
{
|
||||
int i; // Looping var
|
||||
int errors = 0; // Number of errors
|
||||
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
for (i = 1; i < argc; i ++)
|
||||
errors += test_font(argv[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Test with the bundled TrueType files...
|
||||
errors += test_font("testfiles/OpenSans-Bold.ttf");
|
||||
errors += test_font("testfiles/OpenSans-Regular.ttf");
|
||||
errors += test_font("testfiles/NotoSansJP-Regular.otf");
|
||||
}
|
||||
|
||||
if (!errors)
|
||||
puts("\nALL TESTS PASSED");
|
||||
else
|
||||
printf("\n%d TEST(S) FAILED\n", errors);
|
||||
|
||||
return (errors);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'error_cb()' - Error callback.
|
||||
//
|
||||
|
||||
static void
|
||||
error_cb(void *data, // I - User data (not used)
|
||||
const char *message) // I - Message string
|
||||
{
|
||||
fprintf(stderr, "FAIL (%s)\n", message);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'test_font()' - Test a font file.
|
||||
//
|
||||
|
||||
static int // O - Number of errors
|
||||
test_font(const char *filename) // I - Font filename
|
||||
{
|
||||
int i, // Looping var
|
||||
errors = 0; // Number of errors
|
||||
ttf_t *font; // Font
|
||||
const char *value; // Font (string) value
|
||||
int intvalue; // Font (integer) value
|
||||
float realvalue; // Font (real) value
|
||||
ttf_rect_t bounds; // Bounds
|
||||
ttf_rect_t extents; // Extents
|
||||
size_t num_fonts; // Number of fonts
|
||||
ttf_style_t style; // Font style
|
||||
ttf_weight_t weight; // Font weight
|
||||
static const char * const stretches[] =
|
||||
{ // Font stretch strings
|
||||
"TTF_STRETCH_NORMAL", // normal
|
||||
"TTF_STRETCH_ULTRA_CONDENSED", // ultra-condensed
|
||||
"TTF_STRETCH_EXTRA_CONDENSED", // extra-condensed
|
||||
"TTF_STRETCH_CONDENSED", // condensed
|
||||
"TTF_STRETCH_SEMI_CONDENSED", // semi-condensed
|
||||
"TTF_STRETCH_SEMI_EXPANDED", // semi-expanded
|
||||
"TTF_STRETCH_EXPANDED", // expanded
|
||||
"TTF_STRETCH_EXTRA_EXPANDED", // extra-expanded
|
||||
"TTF_STRETCH_ULTRA_EXPANDED" // ultra-expanded
|
||||
};
|
||||
static const char * const strings[] = // Test strings
|
||||
{
|
||||
"Hello, World!", // English
|
||||
"مرحبا بالعالم!", // Arabic
|
||||
"Bonjour le monde!", // French
|
||||
"Γειά σου Κόσμε!", // Greek
|
||||
"שלום עולם!", // Hebrew
|
||||
"Привет мир!", // Russian
|
||||
"こんにちは世界!" // Japanese
|
||||
};
|
||||
static const char * const styles[] = // Font style names
|
||||
{
|
||||
"TTF_STYLE_NORMAL",
|
||||
"TTF_STYLE_ITALIC",
|
||||
"TTF_STYLE_OBLIQUE"
|
||||
};
|
||||
|
||||
|
||||
printf("ttfCreate(\"%s\"): ", filename);
|
||||
fflush(stdout);
|
||||
if ((font = ttfCreate(filename, 0, error_cb, NULL)) != NULL)
|
||||
puts("PASS");
|
||||
else
|
||||
errors ++;
|
||||
|
||||
fputs("ttfGetAscent: ", stdout);
|
||||
if ((intvalue = ttfGetAscent(font)) > 0)
|
||||
{
|
||||
printf("PASS (%d)\n", intvalue);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("FAIL (%d)\n", intvalue);
|
||||
errors ++;
|
||||
}
|
||||
|
||||
fputs("ttfGetBounds: ", stdout);
|
||||
if (ttfGetBounds(font, &bounds))
|
||||
{
|
||||
printf("PASS (%g %g %g %g)\n", bounds.left, bounds.bottom, bounds.right, bounds.top);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("FAIL");
|
||||
errors ++;
|
||||
}
|
||||
|
||||
fputs("ttfGetCapHeight: ", stdout);
|
||||
if ((intvalue = ttfGetCapHeight(font)) > 0)
|
||||
{
|
||||
printf("PASS (%d)\n", intvalue);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("FAIL (%d)\n", intvalue);
|
||||
errors ++;
|
||||
}
|
||||
|
||||
fputs("ttfGetCopyright: ", stdout);
|
||||
if ((value = ttfGetCopyright(font)) != NULL)
|
||||
{
|
||||
printf("PASS (%s)\n", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("WARNING (no copyright found)");
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)(sizeof(strings) / sizeof(strings[0])); i ++)
|
||||
{
|
||||
printf("ttfGetExtents(\"%s\"): ", strings[i]);
|
||||
if (ttfGetExtents(font, 12.0f, strings[i], &extents))
|
||||
{
|
||||
printf("PASS (%.1f %.1f %.1f %.1f)\n", extents.left, extents.bottom, extents.right, extents.top);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("FAIL");
|
||||
errors ++;
|
||||
}
|
||||
}
|
||||
|
||||
fputs("ttfGetFamily: ", stdout);
|
||||
if ((value = ttfGetFamily(font)) != NULL)
|
||||
{
|
||||
printf("PASS (%s)\n", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("FAIL");
|
||||
errors ++;
|
||||
}
|
||||
|
||||
fputs("ttfGetItalicAngle: ", stdout);
|
||||
if ((realvalue = ttfGetItalicAngle(font)) >= -180.0 && realvalue <= 180.0)
|
||||
{
|
||||
printf("PASS (%g)\n", realvalue);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("FAIL (%g)\n", realvalue);
|
||||
errors ++;
|
||||
}
|
||||
|
||||
fputs("ttfGetNumFonts: ", stdout);
|
||||
if ((num_fonts = ttfGetNumFonts(font)) > 0)
|
||||
{
|
||||
printf("PASS (%u)\n", (unsigned)num_fonts);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("FAIL");
|
||||
errors ++;
|
||||
}
|
||||
|
||||
fputs("ttfGetPostScriptName: ", stdout);
|
||||
if ((value = ttfGetPostScriptName(font)) != NULL)
|
||||
{
|
||||
printf("PASS (%s)\n", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("FAIL");
|
||||
errors ++;
|
||||
}
|
||||
|
||||
fputs("ttfGetStretch: ", stdout);
|
||||
if ((intvalue = (int)ttfGetStretch(font)) >= TTF_STRETCH_NORMAL && intvalue <= TTF_STRETCH_ULTRA_EXPANDED)
|
||||
{
|
||||
printf("PASS (%s)\n", stretches[intvalue]);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("FAIL (%d)\n", intvalue);
|
||||
errors ++;
|
||||
}
|
||||
|
||||
fputs("ttfGetStyle: ", stdout);
|
||||
if ((style = ttfGetStyle(font)) >= TTF_STYLE_NORMAL && style <= TTF_STYLE_ITALIC)
|
||||
{
|
||||
printf("PASS (%s)\n", styles[style]);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("FAIL");
|
||||
errors ++;
|
||||
}
|
||||
|
||||
fputs("ttfGetVersion: ", stdout);
|
||||
if ((value = ttfGetVersion(font)) != NULL)
|
||||
{
|
||||
printf("PASS (%s)\n", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("FAIL");
|
||||
errors ++;
|
||||
}
|
||||
|
||||
fputs("ttfGetWeight: ", stdout);
|
||||
if ((weight = ttfGetWeight(font)) >= 0)
|
||||
{
|
||||
printf("PASS (%u)\n", (unsigned)weight);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("FAIL");
|
||||
errors ++;
|
||||
}
|
||||
|
||||
fputs("ttfGetWidth(' '): ", stdout);
|
||||
if ((intvalue = ttfGetWidth(font, ' ')) > 0)
|
||||
{
|
||||
printf("PASS (%d)\n", intvalue);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("FAIL (%d)\n", intvalue);
|
||||
errors ++;
|
||||
}
|
||||
|
||||
fputs("ttfGetXHeight: ", stdout);
|
||||
if ((intvalue = ttfGetXHeight(font)) > 0)
|
||||
{
|
||||
printf("PASS (%d)\n", intvalue);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("FAIL (%d)\n", intvalue);
|
||||
errors ++;
|
||||
}
|
||||
|
||||
fputs("ttfIsFixedPitch: ", stdout);
|
||||
if (ttfIsFixedPitch(font))
|
||||
puts("PASS (true)");
|
||||
else
|
||||
puts("PASS (false)");
|
||||
|
||||
ttfDelete(font);
|
||||
|
||||
return (errors);
|
||||
}
|
||||
1
ttf
110
ttf.h
Normal file
@@ -0,0 +1,110 @@
|
||||
//
|
||||
// Header file for TTF library
|
||||
//
|
||||
// https://github.com/michaelrsweet/ttf
|
||||
//
|
||||
// Copyright © 2018-2024 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
//
|
||||
|
||||
#ifndef TTF_H
|
||||
# define TTF_H
|
||||
# include <stddef.h>
|
||||
# include <stdbool.h>
|
||||
# include <sys/types.h>
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif // __cplusplus
|
||||
|
||||
|
||||
//
|
||||
// Types...
|
||||
//
|
||||
|
||||
typedef struct _ttf_s ttf_t; // Font object
|
||||
|
||||
typedef void (*ttf_err_cb_t)(void *data, const char *message);
|
||||
// Font error callback
|
||||
|
||||
typedef enum ttf_stretch_e // Font stretch
|
||||
{
|
||||
TTF_STRETCH_NORMAL, // normal
|
||||
TTF_STRETCH_ULTRA_CONDENSED, // ultra-condensed
|
||||
TTF_STRETCH_EXTRA_CONDENSED, // extra-condensed
|
||||
TTF_STRETCH_CONDENSED, // condensed
|
||||
TTF_STRETCH_SEMI_CONDENSED, // semi-condensed
|
||||
TTF_STRETCH_SEMI_EXPANDED, // semi-expanded
|
||||
TTF_STRETCH_EXPANDED, // expanded
|
||||
TTF_STRETCH_EXTRA_EXPANDED, // extra-expanded
|
||||
TTF_STRETCH_ULTRA_EXPANDED // ultra-expanded
|
||||
} ttf_stretch_t;
|
||||
|
||||
typedef enum ttf_style_e // Font style
|
||||
{
|
||||
TTF_STYLE_NORMAL, // Normal font
|
||||
TTF_STYLE_ITALIC, // Italic font
|
||||
TTF_STYLE_OBLIQUE // Oblique (angled) font
|
||||
} ttf_style_t;
|
||||
|
||||
typedef enum ttf_variant_e // Font variant
|
||||
{
|
||||
TTF_VARIANT_NORMAL, // Normal font
|
||||
TTF_VARIANT_SMALL_CAPS // Font whose lowercase letters are small capitals
|
||||
} ttf_variant_t;
|
||||
|
||||
typedef enum ttf_weight_e // Font weight
|
||||
{
|
||||
TTF_WEIGHT_100 = 100, // Weight 100 (Thin)
|
||||
TTF_WEIGHT_200 = 200, // Weight 200 (Extra/Ultra-Light)
|
||||
TTF_WEIGHT_300 = 300, // Weight 300 (Light)
|
||||
TTF_WEIGHT_400 = 400, // Weight 400 (Normal/Regular)
|
||||
TTF_WEIGHT_500 = 500, // Weight 500 (Medium)
|
||||
TTF_WEIGHT_600 = 600, // Weight 600 (Semi/Demi-Bold)
|
||||
TTF_WEIGHT_700 = 700, // Weight 700 (Bold)
|
||||
TTF_WEIGHT_800 = 800, // Weight 800 (Extra/Ultra-Bold)
|
||||
TTF_WEIGHT_900 = 900 // Weight 900 (Black/Heavy)
|
||||
} ttf_weight_t;
|
||||
|
||||
typedef struct ttf_rect_s // Bounding rectangle
|
||||
{
|
||||
float left; // Left offset
|
||||
float top; // Top offset
|
||||
float right; // Right offset
|
||||
float bottom; // Bottom offset
|
||||
} ttf_rect_t;
|
||||
|
||||
|
||||
//
|
||||
// Functions...
|
||||
//
|
||||
|
||||
extern ttf_t *ttfCreate(const char *filename, size_t idx, ttf_err_cb_t err_cb, void *err_data);
|
||||
extern void ttfDelete(ttf_t *font);
|
||||
extern int ttfGetAscent(ttf_t *font);
|
||||
extern ttf_rect_t *ttfGetBounds(ttf_t *font, ttf_rect_t *bounds);
|
||||
extern const int *ttfGetCMap(ttf_t *font, size_t *num_cmap);
|
||||
extern int ttfGetCapHeight(ttf_t *font);
|
||||
extern const char *ttfGetCopyright(ttf_t *font);
|
||||
extern int ttfGetDescent(ttf_t *font);
|
||||
extern ttf_rect_t *ttfGetExtents(ttf_t *font, float size, const char *s, ttf_rect_t *extents);
|
||||
extern const char *ttfGetFamily(ttf_t *font);
|
||||
extern float ttfGetItalicAngle(ttf_t *font);
|
||||
extern int ttfGetMaxChar(ttf_t *font);
|
||||
extern int ttfGetMinChar(ttf_t *font);
|
||||
extern size_t ttfGetNumFonts(ttf_t *font);
|
||||
extern const char *ttfGetPostScriptName(ttf_t *font);
|
||||
extern ttf_stretch_t ttfGetStretch(ttf_t *font);
|
||||
extern ttf_style_t ttfGetStyle(ttf_t *font);
|
||||
extern const char *ttfGetVersion(ttf_t *font);
|
||||
extern int ttfGetWidth(ttf_t *font, int ch);
|
||||
extern ttf_weight_t ttfGetWeight(ttf_t *font);
|
||||
extern int ttfGetXHeight(ttf_t *font);
|
||||
extern bool ttfIsFixedPitch(ttf_t *font);
|
||||
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif // __cplusplus
|
||||
#endif // !TTF_H
|
||||