mirror of
https://github.com/michaelrsweet/pdfio.git
synced 2025-07-14 21:09:52 +02:00
Compare commits
27 Commits
v1.1.2
...
16c8b830b8
Author | SHA1 | Date | |
---|---|---|---|
16c8b830b8 | |||
7ff051fc8b | |||
927452d1eb | |||
f1ad982fd1 | |||
c188cb8dad | |||
4919783da5 | |||
86281750e5 | |||
d92b72ed02 | |||
a195c023af | |||
43000ff01f | |||
c6f17cc20f | |||
41146adbdf | |||
cd80c3037d | |||
97934ab995 | |||
088646e1cf | |||
3f0aad7564 | |||
d36df63b57 | |||
a5dfac7495 | |||
0258384d53 | |||
9fec2195d0 | |||
8ccbdaed94 | |||
4804db38a5 | |||
ddd984215a | |||
efe7c01015 | |||
600fa4ce59 | |||
688810f143 | |||
858cc101b6 |
39
.github/workflows/build.yml
vendored
39
.github/workflows/build.yml
vendored
@ -9,23 +9,26 @@ on:
|
||||
jobs:
|
||||
build-linux:
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: update build environment
|
||||
- name: Checkout PDFio sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Update Build Environment
|
||||
run: sudo apt-get update --fix-missing -y
|
||||
- name: install prerequisites
|
||||
- name: Install Prerequisites
|
||||
run: sudo apt-get install -y cppcheck zlib1g-dev
|
||||
- name: make
|
||||
- name: Configure PDFio
|
||||
run: ./configure --enable-debug --enable-sanitizer --enable-maintainer
|
||||
- name: Build PDFio
|
||||
run: make "COMMONFLAGS=-g -fsanitize=address"
|
||||
- name: test
|
||||
- name: Test PDFio
|
||||
env:
|
||||
ASAN_OPTIONS: leak_check_at_exit=false
|
||||
run: make test
|
||||
- name: clang static analyzer
|
||||
- name: Run Clang Static Analyzer
|
||||
run: make CC=clang "GHA_ERROR=::error::" clang
|
||||
- name: cppcheck
|
||||
- name: Run cppcheck
|
||||
run: make "GHA_ERROR=::error::" cppcheck
|
||||
|
||||
build-macos:
|
||||
@ -33,12 +36,15 @@ jobs:
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: make
|
||||
- name: Checkout PDFio sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Configure PDFio
|
||||
run: ./configure --enable-debug --enable-sanitizer --enable-maintainer
|
||||
- name: Build PDFio
|
||||
run: make "COMMONFLAGS=-g -fsanitize=address"
|
||||
- name: test
|
||||
- name: Test PDFio
|
||||
run: make test
|
||||
- name: clang static analyzer
|
||||
- name: Run Clang Static Analyzer
|
||||
run: make CC=clang "GHA_ERROR=::error::" clang
|
||||
|
||||
build-windows:
|
||||
@ -46,10 +52,11 @@ jobs:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: setup-msbuild
|
||||
- name: Checkout PDFio sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup MSBuild
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
- name: nuget restore
|
||||
- name: Nuget Restore
|
||||
run: nuget restore pdfio.sln
|
||||
- name: msbuild
|
||||
- name: Build PDFio
|
||||
run: msbuild pdfio.sln
|
||||
|
8
.github/workflows/codeql.yml
vendored
8
.github/workflows/codeql.yml
vendored
@ -23,15 +23,15 @@ jobs:
|
||||
language: [ cpp ]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Checkout PDFio sources
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Update build environment
|
||||
- name: Update Build Environment
|
||||
run: sudo apt-get update --fix-missing -y
|
||||
|
||||
- name: Install prerequisites
|
||||
- name: Install Prerequisites
|
||||
run: sudo apt-get install -y zlib1g-dev
|
||||
|
||||
- name: Initialize CodeQL
|
||||
|
15
.github/workflows/coverity.yml
vendored
15
.github/workflows/coverity.yml
vendored
@ -7,10 +7,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
environment: Coverity
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: update build environment
|
||||
- name: Checkout PDFio sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Update Build Environment
|
||||
run: sudo apt-get update --fix-missing -y
|
||||
- name: install prerequisites
|
||||
- name: Install Prerequisites
|
||||
run: sudo apt-get install -y zlib1g-dev
|
||||
- name: Download Coverity Build Tool
|
||||
run: |
|
||||
@ -20,11 +21,15 @@ jobs:
|
||||
env:
|
||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||
|
||||
- name: Build with cov-build
|
||||
- name: Configure PDFio
|
||||
run: ./configure --enable-debug --enable-maintainer
|
||||
|
||||
- name: Build PDFio with cov-build
|
||||
run: |
|
||||
export PATH=`pwd`/cov-analysis-linux64/bin:$PATH
|
||||
cov-build --dir cov-int make
|
||||
- name: Submit the result to Coverity Scan
|
||||
|
||||
- name: Submit the Result to Coverity Scan
|
||||
run: |
|
||||
tar czvf cov.tgz cov-int
|
||||
curl \
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -5,12 +5,18 @@
|
||||
*.so.1
|
||||
/.vs
|
||||
/afl-output
|
||||
/autom4te.cache
|
||||
/config.log
|
||||
/config.status
|
||||
/doc/pdfio.epub
|
||||
/Makefile
|
||||
/packages
|
||||
/pdfio.pc
|
||||
/pdfio.xcodeproj/xcshareddata
|
||||
/pdfio-*.tar.gz*
|
||||
/pdfio-*.zip*
|
||||
/pdfiototext
|
||||
/testpdfio
|
||||
/testpdfio-*.pdf
|
||||
/testttf
|
||||
/x64
|
||||
|
28
CHANGES.md
28
CHANGES.md
@ -2,6 +2,34 @@ Changes in PDFio
|
||||
================
|
||||
|
||||
|
||||
v1.2.0 (Month DD, YYYY)
|
||||
-----------------------
|
||||
|
||||
- Added `pdfioFileCreateNumberObj` and `pdfioFileCreateStringObj` functions
|
||||
(Issue #14)
|
||||
- Added `pdfioContentTextMeasure` function (Issue #17)
|
||||
- Added `pdfioContentTextNewLineShow` and `pdfioContentTextNewLineShowf`
|
||||
functions (Issue #24)
|
||||
- Renamed `pdfioContentTextNextLine` to `pdfioContentTextNewLine`.
|
||||
- Now use autoconf to configure the PDFio sources (Issue #54)
|
||||
|
||||
|
||||
v1.1.4 (December 3, 2023)
|
||||
-------------------------
|
||||
|
||||
- Fixed detection of encrypted strings that are too short (Issue #52)
|
||||
- Fixed a TrueType CMAP decoding bug.
|
||||
- Fixed a text rendering issue for Asian text.
|
||||
- Added a ToUnicode map for Unicode text to support text copying.
|
||||
|
||||
|
||||
v1.1.3 (November 15, 2023)
|
||||
--------------------------
|
||||
|
||||
- Fixed Unicode font support (Issue #16)
|
||||
- Fixed missing initializer for 40-bit RC4 encryption (Issue #51)
|
||||
|
||||
|
||||
v1.1.2 (October 10, 2023)
|
||||
-------------------------
|
||||
|
||||
|
224
Makefile
224
Makefile
@ -1,224 +0,0 @@
|
||||
#
|
||||
# Makefile for PDFio.
|
||||
#
|
||||
# Copyright © 2021-2023 by Michael R Sweet.
|
||||
#
|
||||
# Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
# information.
|
||||
#
|
||||
|
||||
# POSIX makefile
|
||||
.POSIX:
|
||||
|
||||
# Build silently
|
||||
.SILENT:
|
||||
|
||||
# Variables
|
||||
AR = ar
|
||||
ARFLAGS = cr
|
||||
CC = cc
|
||||
CFLAGS =
|
||||
CODESIGN_IDENTITY = Developer ID
|
||||
COMMONFLAGS = -Os -g
|
||||
#COMMONFLAGS = -O0 -g -fsanitize=address
|
||||
CPPFLAGS =
|
||||
DESTDIR = $(DSTROOT)
|
||||
DSO = cc
|
||||
DSOFLAGS =
|
||||
DSONAME =
|
||||
LDFLAGS =
|
||||
LIBS = -lm -lz
|
||||
RANLIB = ranlib
|
||||
VERSION = 1.1.2
|
||||
prefix = /usr/local
|
||||
|
||||
|
||||
# Base rules
|
||||
.SUFFIXES: .c .h .o
|
||||
.c.o:
|
||||
echo Compiling $<...
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $(COMMONFLAGS) -c $<
|
||||
|
||||
|
||||
# Files
|
||||
PUBHEADERS = \
|
||||
pdfio.h \
|
||||
pdfio-content.h
|
||||
PUBOBJS = \
|
||||
pdfio-aes.o \
|
||||
pdfio-array.o \
|
||||
pdfio-common.o \
|
||||
pdfio-content.o \
|
||||
pdfio-crypto.o \
|
||||
pdfio-dict.o \
|
||||
pdfio-file.o \
|
||||
pdfio-md5.o \
|
||||
pdfio-object.o \
|
||||
pdfio-page.o \
|
||||
pdfio-rc4.o \
|
||||
pdfio-sha256.o \
|
||||
pdfio-stream.o \
|
||||
pdfio-string.o \
|
||||
pdfio-token.o \
|
||||
pdfio-value.o
|
||||
LIBOBJS = \
|
||||
$(PUBOBJS) \
|
||||
ttf.o
|
||||
OBJS = \
|
||||
$(LIBOBJS) \
|
||||
pdfiototext.o \
|
||||
testpdfio.o
|
||||
TARGETS = \
|
||||
$(DSONAME) \
|
||||
libpdfio.a \
|
||||
pdfiototext \
|
||||
testpdfio
|
||||
|
||||
|
||||
# Make everything
|
||||
all: $(TARGETS)
|
||||
|
||||
all-shared:
|
||||
if test `uname` = Darwin; then \
|
||||
$(MAKE) DSONAME="libpdfio.1.dylib" -$(MAKEFLAGS) all; \
|
||||
else \
|
||||
$(MAKE) COMMONFLAGS="-g -Os -fPIC" DSONAME="libpdfio.so.1" -$(MAKEFLAGS) all; \
|
||||
fi
|
||||
|
||||
debug:
|
||||
$(MAKE) -$(MAKEFLAGS) COMMONFLAGS="-g -fsanitize=address -DDEBUG=1" clean all
|
||||
|
||||
macos:
|
||||
$(MAKE) -$(MAKEFLAGS) COMMONFLAGS="-Os -mmacosx-version-min=11 -arch x86_64 -arch arm64" clean all
|
||||
|
||||
|
||||
# Clean everything
|
||||
clean:
|
||||
rm -f $(TARGETS) $(OBJS)
|
||||
|
||||
|
||||
# Install everything
|
||||
install: $(TARGETS)
|
||||
echo Installing header files to $(DESTDIR)$(prefix)/include...
|
||||
-mkdir -p $(DESTDIR)$(prefix)/include
|
||||
cp $(PUBHEADERS) $(DESTDIR)$(prefix)/include
|
||||
echo Installing library files to $(DESTDIR)$(prefix)/lib...
|
||||
-mkdir -p $(DESTDIR)$(prefix)/lib
|
||||
cp libpdfio.a $(DESTDIR)$(prefix)/lib
|
||||
$(RANLIB) $(DESTDIR)$(prefix)/lib/libpdfio.a
|
||||
if test "x$(DSONAME)" = xlibpdfio.so.1; then \
|
||||
cp $(DSONAME) $(DESTDIR)$(prefix)/lib; \
|
||||
ln -sf libpdfio.so.1 $(DESTDIR)$(prefix)/lib/libpdfio.so; \
|
||||
elif test "x$(DSONAME)" = xlibpdfio.1.dylib; then \
|
||||
cp $(DSONAME) $(DESTDIR)$(prefix)/lib; \
|
||||
codesign -s "$(CODESIGN_IDENTITY)" -o runtime --timestamp $(DESTDIR)$(prefix)/lib/libpdfio.1.dylib; \
|
||||
ln -sf libpdfio.1.dylib $(DESTDIR)$(prefix)/lib/libpdfio.dylib; \
|
||||
fi
|
||||
echo Installing pkg-config files to $(DESTDIR)$(prefix)/lib/pkgconfig...
|
||||
-mkdir -p $(DESTDIR)$(prefix)/lib/pkgconfig
|
||||
echo 'prefix="$(prefix)"' >$(DESTDIR)$(prefix)/lib/pkgconfig/pdfio.pc
|
||||
echo 'Version: $(VERSION)' >>$(DESTDIR)$(prefix)/lib/pkgconfig/pdfio.pc
|
||||
cat pdfio.pc.in >>$(DESTDIR)$(prefix)/lib/pkgconfig/pdfio.pc
|
||||
echo Installing documentation to $(DESTDIR)$(prefix)/share/doc/pdfio...
|
||||
-mkdir -p $(DESTDIR)$(prefix)/share/doc/pdfio
|
||||
cp doc/pdfio.html doc/pdfio-512.png LICENSE NOTICE $(DESTDIR)$(prefix)/share/doc/pdfio
|
||||
echo Installing man page to $(DESTDIR)$(prefix)/share/man/man3...
|
||||
-mkdir -p $(DESTDIR)$(prefix)/share/man/man3
|
||||
cp doc/pdfio.3 $(DESTDIR)$(prefix)/share/man/man3
|
||||
|
||||
install-shared:
|
||||
if test `uname` = Darwin; then \
|
||||
$(MAKE) DSONAME="libpdfio.1.dylib" -$(MAKEFLAGS) install; \
|
||||
else \
|
||||
$(MAKE) DSONAME="libpdfio.so.1" -$(MAKEFLAGS) install; \
|
||||
fi
|
||||
|
||||
|
||||
# Test everything
|
||||
test: testpdfio
|
||||
./testpdfio 2>test.log
|
||||
|
||||
valgrind: testpdfio
|
||||
valgrind --leak-check=full ./testpdfio
|
||||
|
||||
|
||||
# pdfio library
|
||||
libpdfio.a: $(LIBOBJS)
|
||||
echo Archiving $@...
|
||||
$(AR) $(ARFLAGS) $@ $(LIBOBJS)
|
||||
$(RANLIB) $@
|
||||
|
||||
libpdfio.so.1: $(LIBOBJS)
|
||||
echo Linking $@...
|
||||
$(CC) $(DSOFLAGS) $(COMMONFLAGS) -shared -o $@ -Wl,-soname,$@ $(LIBOBJS) $(LIBS)
|
||||
|
||||
libpdfio.1.dylib: $(LIBOBJS)
|
||||
echo Linking $@...
|
||||
$(CC) $(DSOFLAGS) $(COMMONFLAGS) -dynamiclib -o $@ -install_name $(prefix)/lib/$@ -current_version $(VERSION) -compatibility_version 1.0 $(LIBOBJS) $(LIBS)
|
||||
|
||||
|
||||
# pdfio1.def (Windows DLL exports file...)
|
||||
#
|
||||
# I'd love to use __declspec(dllexport) but MS puts it before the function
|
||||
# declaration instead of after like everyone else, and it breaks Codedoc and
|
||||
# other tools I rely on...
|
||||
pdfio1.def: $(LIBOBJS) Makefile
|
||||
echo Generating $@...
|
||||
echo "LIBRARY pdfio1" >$@
|
||||
echo "VERSION 1.0" >>$@
|
||||
echo "EXPORTS" >>$@
|
||||
nm $(LIBOBJS) 2>/dev/null | grep "T _" | awk '{print $$3}' | \
|
||||
grep -v '^_ttf' | sed -e '1,$$s/^_//' | sort >>$@
|
||||
|
||||
|
||||
# pdfio text extraction (demo, doesn't handle a lot of things yet)
|
||||
pdfiototext: pdfiototext.o libpdfio.a
|
||||
echo Linking $@...
|
||||
$(CC) $(LDFLAGS) $(COMMONFLAGS) -o $@ pdfiototext.o libpdfio.a $(LIBS)
|
||||
|
||||
|
||||
# pdfio test program
|
||||
testpdfio: testpdfio.o libpdfio.a
|
||||
echo Linking $@...
|
||||
$(CC) $(LDFLAGS) $(COMMONFLAGS) -o $@ testpdfio.o libpdfio.a $(LIBS)
|
||||
|
||||
|
||||
# Dependencies
|
||||
$(OBJS): pdfio.h pdfio-private.h Makefile
|
||||
pdfio-content.o: pdfio-content.h ttf.h
|
||||
ttf.o: ttf.h
|
||||
|
||||
# Make documentation using Codedoc <https://www.msweet.org/codedoc>
|
||||
DOCFLAGS = \
|
||||
--author "Michael R Sweet" \
|
||||
--copyright "Copyright (c) 2021-2023 by Michael R Sweet" \
|
||||
--docversion $(VERSION)
|
||||
|
||||
.PHONY: doc
|
||||
doc:
|
||||
echo Generating documentation...
|
||||
codedoc $(DOCFLAGS) --title "PDFio Programming Manual v$(VERSION)" $(PUBHEADERS) $(PUBOBJS:.o=.c) --body doc/pdfio.md --coverimage doc/pdfio-512.png pdfio.xml >doc/pdfio.html
|
||||
codedoc $(DOCFLAGS) --title "PDFio Programming Manual v$(VERSION)" --body doc/pdfio.md --coverimage doc/pdfio-epub.png pdfio.xml --epub doc/pdfio.epub
|
||||
codedoc $(DOCFLAGS) --title "pdf read/write library" --man pdfio --section 3 --body doc/pdfio.md pdfio.xml >doc/pdfio.3
|
||||
rm -f pdfio.xml
|
||||
|
||||
|
||||
# Fuzz-test the library <>
|
||||
.PHONY: afl
|
||||
afl:
|
||||
$(MAKE) -$(MAKEFLAGS) CC="afl-clang-fast" COMMONFLAGS="-g" clean all
|
||||
test afl-output || rm -rf afl-output
|
||||
afl-fuzz -x afl-pdf.dict -i afl-input -o afl-output -V 600 -e pdf -t 5000 ./testpdfio @@
|
||||
|
||||
|
||||
# Analyze code with the Clang static analyzer <https://clang-analyzer.llvm.org>
|
||||
clang:
|
||||
clang $(CPPFLAGS) --analyze $(OBJS:.o=.c) 2>clang.log
|
||||
rm -rf $(OBJS:.o=.plist)
|
||||
test -s clang.log && (echo "$(GHA_ERROR)Clang detected issues."; echo ""; cat clang.log; exit 1) || exit 0
|
||||
|
||||
|
||||
# Analyze code using Cppcheck <http://cppcheck.sourceforge.net>
|
||||
cppcheck:
|
||||
cppcheck $(CPPFLAGS) --template=gcc --addon=cert.py --suppressions-list=.cppcheck $(OBJS:.o=.c) 2>cppcheck.log
|
||||
test -s cppcheck.log && (echo "$(GHA_ERROR)Cppcheck detected issues."; echo ""; cat cppcheck.log; exit 1) || exit 0
|
259
Makefile.in
Normal file
259
Makefile.in
Normal file
@ -0,0 +1,259 @@
|
||||
#
|
||||
# Makefile for PDFio.
|
||||
#
|
||||
# Copyright © 2021-2023 by Michael R Sweet.
|
||||
#
|
||||
# Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
# information.
|
||||
#
|
||||
|
||||
# POSIX makefile
|
||||
.POSIX:
|
||||
|
||||
|
||||
# Build silently
|
||||
.SILENT:
|
||||
|
||||
|
||||
# Version number...
|
||||
PDFIO_VERSION = @PDFIO_VERSION@
|
||||
PDFIO_VERSION_MAJOR = @PDFIO_VERSION_MAJOR@
|
||||
PDFIO_VERSION_MINOR = @PDFIO_VERSION_MINOR@
|
||||
|
||||
|
||||
# Programs and options...
|
||||
AR = @AR@
|
||||
ARFLAGS = @ARFLAGS@
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@ $(CPPFLAGS) $(OPTIM) $(WARNINGS)
|
||||
CODE_SIGN = @CODE_SIGN@
|
||||
CODESIGN_IDENTITY = -
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CSFLAGS = -s "$(CODESIGN_IDENTITY)" @CSFLAGS@ --timestamp
|
||||
DSOFLAGS = @DSOFLAGS@ $(CFLAGS)
|
||||
INSTALL = @INSTALL@
|
||||
LDFLAGS = @LDFLAGS@ $(OPTIM)
|
||||
LIBS = @LIBS@ -lm
|
||||
LN = @LN@
|
||||
OPTIM = @OPTIM@
|
||||
RANLIB = @RANLIB@
|
||||
RM = @RM@ -f
|
||||
RMDIR = @RMDIR@
|
||||
SHELL = /bin/sh
|
||||
WARNINGS = @WARNINGS@
|
||||
|
||||
|
||||
# Targets
|
||||
LIBPDFIO = @LIBPDFIO@
|
||||
LIBPDFIO_STATIC = @LIBPDFIO_STATIC@
|
||||
|
||||
|
||||
# Directories...
|
||||
bindir = @bindir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
exec_prefix = @exec_prefix@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
oldincludedir = @oldincludedir@
|
||||
prefix = @prefix@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
BUILDROOT = $(DSTROOT)$(RPM_BUILD_ROOT)$(DESTDIR)
|
||||
|
||||
|
||||
# Build commands...
|
||||
.SUFFIXES: .c .h .o
|
||||
.c.o:
|
||||
echo Compiling $<...
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
|
||||
# Files
|
||||
PUBHEADERS = \
|
||||
pdfio.h \
|
||||
pdfio-content.h
|
||||
PUBOBJS = \
|
||||
pdfio-aes.o \
|
||||
pdfio-array.o \
|
||||
pdfio-common.o \
|
||||
pdfio-content.o \
|
||||
pdfio-crypto.o \
|
||||
pdfio-dict.o \
|
||||
pdfio-file.o \
|
||||
pdfio-md5.o \
|
||||
pdfio-object.o \
|
||||
pdfio-page.o \
|
||||
pdfio-rc4.o \
|
||||
pdfio-sha256.o \
|
||||
pdfio-stream.o \
|
||||
pdfio-string.o \
|
||||
pdfio-token.o \
|
||||
pdfio-value.o
|
||||
LIBOBJS = \
|
||||
$(PUBOBJS) \
|
||||
ttf.o
|
||||
OBJS = \
|
||||
$(LIBOBJS) \
|
||||
pdfiototext.o \
|
||||
testpdfio.o \
|
||||
testttf.o
|
||||
TARGETS = \
|
||||
$(LIBPDFIO) \
|
||||
$(LIBPDFIO_STATIC) \
|
||||
pdfiototext \
|
||||
testpdfio \
|
||||
testttf
|
||||
|
||||
|
||||
# Make everything
|
||||
all: $(TARGETS)
|
||||
|
||||
|
||||
# Clean everything
|
||||
clean:
|
||||
rm -f $(TARGETS) $(OBJS)
|
||||
|
||||
|
||||
# Install everything
|
||||
install: $(TARGETS)
|
||||
echo Installing header files to $(BUILDROOT)$(includedir)...
|
||||
$(INSTALL) -d -m 755 $(BUILDROOT)$(includedir)
|
||||
for file in $(PUBHEADERS); do \
|
||||
$(INSTALL) -c -m 644 $$file $(BUILDROOT)$(includedir); \
|
||||
done
|
||||
echo Installing library files to $(BUILDROOT)$(libdir)...
|
||||
$(INSTALL) -d -m 755 $(BUILDROOT)$(libdir)
|
||||
if test "x$(LIBPDFIO_STATIC)" != x; then \
|
||||
$(INSTALL) -c -m 644 $(LIBPDFIO_STATIC) $(BUILDROOT)$(libdir); \
|
||||
$(RANLIB) $(BUILDROOT)$(libdir)/$(LIBPDFIO_STATIC); \
|
||||
fi
|
||||
if test "x$(LIBPDFIO)" = xlibpdfio.so.1; then \
|
||||
$(INSTALL) -c -m 755 libpdfio.so.1 $(BUILDROOT)$(libdir); \
|
||||
ln -sf libpdfio.so.1 $(BUILDROOT)$(libdir)/libpdfio.so; \
|
||||
elif test "x$(LIBPDFIO)" = xlibpdfio.1.dylib; then \
|
||||
$(INSTALL) -c -m 755 libpdfio.1.dylib $(BUILDROOT)$(libdir); \
|
||||
codesign -s "$(CODESIGN_IDENTITY)" -o runtime --timestamp $(BUILDROOT)$(libdir)/libpdfio.1.dylib; \
|
||||
ln -sf libpdfio.1.dylib $(BUILDROOT)$(libdir)/libpdfio.dylib; \
|
||||
else \
|
||||
$(INSTALL) -c -m 644 $(LIBPDFIO) $(BUILDROOT)$(libdir); \
|
||||
$(RANLIB) $(BUILDROOT)$(libdir)/$(LIBPDFIO); \
|
||||
fi
|
||||
echo Installing pkg-config files to $(BUILDROOT)$(libdir)/pkgconfig...
|
||||
$(INSTALL) -d -m 755 $(BUILDROOT)$(libdir)/pkgconfig
|
||||
$(INSTALL) -c -m 644 pdfio.pc $(BUILDROOT)$(libdir)/pkgconfig
|
||||
echo Installing documentation to $(BUILDROOT)$(datadir)/doc/pdfio...
|
||||
$(INSTALL) -d -m 755 $(BUILDROOT)$(datadir)/doc/pdfio
|
||||
for file in doc/pdfio.html doc/pdfio-512.png LICENSE NOTICE; do \
|
||||
$(INSTALL) -c -m 644 $$file $(BUILDROOT)$(datadir)/doc/pdfio; \
|
||||
done
|
||||
echo Installing man page to $(BUILDROOT)$(mandir)/man3...
|
||||
$(INSTALL) -d -m 755 $(BUILDROOT)$(mandir)/man3
|
||||
$(INSTALL) -c -m 644 doc/pdfio.3 $(BUILDROOT)$(mandir)/man3
|
||||
|
||||
|
||||
# Test everything
|
||||
test: testpdfio testttf
|
||||
./testttf 2>test.log
|
||||
./testpdfio 2>test.log
|
||||
|
||||
valgrind: testpdfio
|
||||
valgrind --leak-check=full ./testpdfio
|
||||
|
||||
|
||||
# pdfio library
|
||||
libpdfio.a: $(LIBOBJS)
|
||||
echo Archiving $@...
|
||||
$(AR) $(ARFLAGS) $@ $(LIBOBJS)
|
||||
$(RANLIB) $@
|
||||
|
||||
libpdfio.so.1: $(LIBOBJS)
|
||||
echo Linking $@...
|
||||
$(CC) $(DSOFLAGS) -shared -o $@ -Wl,-soname,$@ $(LIBOBJS) $(LIBS)
|
||||
|
||||
libpdfio.1.dylib: $(LIBOBJS)
|
||||
echo Linking $@...
|
||||
$(CC) $(DSOFLAGS) -dynamiclib -o $@ -install_name $(libdir)/$@ -current_version $(PDFIO_VERSION_MAJOR).$(PDFIO_VERSION_MINOR) -compatibility_version 1.0 $(LIBOBJS) $(LIBS)
|
||||
|
||||
|
||||
# pdfio1.def (Windows DLL exports file...)
|
||||
#
|
||||
# I'd love to use __declspec(dllexport) but MS puts it before the function
|
||||
# declaration instead of after like everyone else, and it breaks Codedoc and
|
||||
# other tools I rely on...
|
||||
pdfio1.def: $(LIBOBJS) Makefile
|
||||
echo Generating $@...
|
||||
echo "LIBRARY pdfio1" >$@
|
||||
echo "VERSION $(PDFIO_VERSION_MAJOR).$(PDFIO_VERSION_MINOR)" >>$@
|
||||
echo "EXPORTS" >>$@
|
||||
nm $(LIBOBJS) 2>/dev/null | grep "T _" | awk '{print $$3}' | \
|
||||
grep -v '^_ttf' | sed -e '1,$$s/^_//' | sort >>$@
|
||||
|
||||
|
||||
# pdfio text extraction (demo, doesn't handle a lot of things yet)
|
||||
pdfiototext: pdfiototext.o libpdfio.a
|
||||
echo Linking $@...
|
||||
$(CC) $(LDFLAGS) -o $@ pdfiototext.o libpdfio.a $(LIBS)
|
||||
|
||||
|
||||
# pdfio test program
|
||||
testpdfio: testpdfio.o libpdfio.a
|
||||
echo Linking $@...
|
||||
$(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 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-2023 by Michael R Sweet" \
|
||||
--docversion $(PDFIO_VERSION)
|
||||
|
||||
.PHONY: doc
|
||||
doc:
|
||||
echo Generating documentation...
|
||||
codedoc $(DOCFLAGS) --title "PDFio Programming Manual v$(PDFIO_VERSION)" $(PUBHEADERS) $(PUBOBJS:.o=.c) --body doc/pdfio.md --coverimage doc/pdfio-512.png pdfio.xml >doc/pdfio.html
|
||||
codedoc $(DOCFLAGS) --title "PDFio Programming Manual v$(PDFIO_VERSION)" --body doc/pdfio.md --coverimage doc/pdfio-epub.png pdfio.xml --epub doc/pdfio.epub
|
||||
codedoc $(DOCFLAGS) --title "pdf read/write library" --man pdfio --section 3 --body doc/pdfio.md pdfio.xml >doc/pdfio.3
|
||||
rm -f pdfio.xml
|
||||
|
||||
|
||||
# Fuzz-test the library <https://lcamtuf.coredump.cx/afl/>
|
||||
.PHONY: afl
|
||||
afl:
|
||||
$(MAKE) -$(MAKEFLAGS) CC="afl-clang-fast" COMMONFLAGS="-g" clean all
|
||||
test afl-output || rm -rf afl-output
|
||||
afl-fuzz -x afl-pdf.dict -i afl-input -o afl-output -V 600 -e pdf -t 5000 ./testpdfio @@
|
||||
|
||||
|
||||
# Analyze code with the Clang static analyzer <https://clang-analyzer.llvm.org>
|
||||
clang:
|
||||
clang $(CPPFLAGS) --analyze $(OBJS:.o=.c) 2>clang.log
|
||||
rm -rf $(OBJS:.o=.plist)
|
||||
test -s clang.log && (echo "$(GHA_ERROR)Clang detected issues."; echo ""; cat clang.log; exit 1) || exit 0
|
||||
|
||||
|
||||
# Analyze code using Cppcheck <http://cppcheck.sourceforge.net>
|
||||
cppcheck:
|
||||
cppcheck $(CPPFLAGS) --template=gcc --addon=cert.py --suppressions-list=.cppcheck $(OBJS:.o=.c) 2>cppcheck.log
|
||||
test -s cppcheck.log && (echo "$(GHA_ERROR)Cppcheck detected issues."; echo ""; cat cppcheck.log; exit 1) || exit 0
|
68
README.md
68
README.md
@ -28,7 +28,7 @@ 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.0 or higher
|
||||
- ZLIB (<https://www.zlib.net>) 1.1 or higher
|
||||
|
||||
IDE files for Xcode (macOS/iOS) and Visual Studio (Windows) are also provided.
|
||||
|
||||
@ -36,15 +36,27 @@ IDE files for Xcode (macOS/iOS) and Visual Studio (Windows) are also provided.
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
See the man page (`pdfio.3`), frequently ask questions (`FAQ.md`), and full HTML
|
||||
documentation (`pdfio.html`) for information on using PDFio.
|
||||
See the man page (`pdfio.3`) and full HTML documentation (`pdfio.html`) for
|
||||
information on using PDFio.
|
||||
|
||||
|
||||
Installing pdfio
|
||||
Installing PDFio
|
||||
----------------
|
||||
|
||||
PDFio comes with a portable makefile that will work on any POSIX-compliant
|
||||
system with ZLIB installed. To make it, run:
|
||||
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
|
||||
|
||||
Once configured, run the following to make the library:
|
||||
|
||||
make all
|
||||
|
||||
@ -54,45 +66,7 @@ To test it, run:
|
||||
|
||||
To install it, run:
|
||||
|
||||
make install
|
||||
|
||||
If you want a shared library, run:
|
||||
|
||||
make all-shared
|
||||
make install-shared
|
||||
|
||||
The default installation location is "/usr/local". Pass the `prefix` variable
|
||||
to make to install it to another location:
|
||||
|
||||
make install prefix=/some/other/directory
|
||||
|
||||
The makefile installs the pdfio header to "${prefix}/include", the library to
|
||||
"${prefix}/lib", the `pkg-config` file to "${prefix}/lib/pkgconfig", the man
|
||||
page to "${prefix}/share/man/man3", and the documentation to
|
||||
"${prefix}/share/doc/pdfio".
|
||||
|
||||
The makefile supports the following variables that can be specified in the make
|
||||
command or as environment variables:
|
||||
|
||||
- `AR`: the library archiver (default "ar")
|
||||
- `ARFLAGS`: options for the library archiver (default "cr")
|
||||
- `CC`: the C compiler (default "cc")
|
||||
- `CFLAGS`: options for the C compiler (default "")
|
||||
- `CODESIGN_IDENTITY`: the identity to use when code signing the shared library
|
||||
on macOS (default "Developer ID")
|
||||
- `COMMONFLAGS`: options for the C compiler and linker (typically architecture
|
||||
and optimization options, default is "-Os -g")
|
||||
- `CPPFLAGS`: options for the C preprocessor (default "")
|
||||
- `DESTDIR` and `DSTROOT`: specifies a root directory when installing
|
||||
(default is "", specify only one)
|
||||
- `DSOFLAGS`: options for the C compiler when linking the shared library
|
||||
(default "")
|
||||
- `LDFLAGS`: options for the C compiler when linking the test programs
|
||||
(default "")
|
||||
- `LIBS`: library options when linking the test programs (default "-lz")
|
||||
- `RANLIB`: program that generates a table-of-contents in a library
|
||||
(default "ranlib")
|
||||
- `prefix`: specifies the installation directory (default "/usr/local")
|
||||
sudo make install
|
||||
|
||||
|
||||
Visual Studio Project
|
||||
@ -111,10 +85,6 @@ generates a static library that will be installed under "/usr/local" with:
|
||||
|
||||
sudo xcodebuild install
|
||||
|
||||
You can reproduce this with the makefile using:
|
||||
|
||||
sudo make macos install
|
||||
|
||||
|
||||
Legal Stuff
|
||||
-----------
|
||||
|
1774
config.guess
vendored
Executable file
1774
config.guess
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1907
config.sub
vendored
Executable file
1907
config.sub
vendored
Executable file
File diff suppressed because it is too large
Load Diff
272
configure.ac
Normal file
272
configure.ac
Normal file
@ -0,0 +1,272 @@
|
||||
dnl
|
||||
dnl Configuration script for PDFio
|
||||
dnl
|
||||
dnl Copyright © 2023 by Michael R Sweet
|
||||
dnl
|
||||
dnl Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
dnl information.
|
||||
dnl
|
||||
|
||||
dnl ***********************************************************************
|
||||
dnl
|
||||
dnl Note: Using autoheader or automake on this project will break the PDFio
|
||||
dnl build system. Use "autoconf -f" to regenerate the configure script if
|
||||
dnl you make changes to this file.
|
||||
dnl
|
||||
dnl ***********************************************************************
|
||||
|
||||
|
||||
dnl We need at least autoconf 2.70 for --runstatedir...
|
||||
AC_PREREQ([2.70])
|
||||
|
||||
|
||||
dnl Package name and version...
|
||||
AC_INIT([pdfio], [1.2.0], [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}'`"
|
||||
PDFIO_VERSION_MINOR="`echo AC_PACKAGE_VERSION | awk -F. '{printf("%d\n",$2);}'`"
|
||||
AC_SUBST([PDFIO_VERSION])
|
||||
AC_SUBST([PDFIO_VERSION_MAJOR])
|
||||
AC_SUBST([PDFIO_VERSION_MINOR])
|
||||
|
||||
|
||||
dnl This line is provided to ensure that you don't run the autoheader program
|
||||
dnl against this project. Doing so is completely unsupported and WILL cause
|
||||
dnl problems!
|
||||
AH_TOP([#error "Somebody ran autoheader on this project which is unsupported and WILL cause problems."])
|
||||
|
||||
|
||||
dnl Get the build and host platforms and split the host_os value
|
||||
AC_CANONICAL_BUILD
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
[host_os_name="$(echo $host_os | sed -e '1,$s/[0-9.]*$//g')"]
|
||||
[host_os_version="$(echo $host_os | sed -e '1,$s/^[^0-9.]*//g' | awk -F. '{print $1 $2}')"]
|
||||
# Linux often does not yield an OS version we can use...
|
||||
AS_IF([test "x$host_os_version" = x], [
|
||||
host_os_version="0"
|
||||
])
|
||||
|
||||
|
||||
dnl Compiler options...
|
||||
CFLAGS="${CFLAGS:=}"
|
||||
CPPFLAGS="${CPPFLAGS:=}"
|
||||
DSOFLAGS="${DSOFLAGS:=}"
|
||||
LDFLAGS="${LDFLAGS:=}"
|
||||
LIBS="${LIBS:=}"
|
||||
OPTIM="${OPTIM:=}"
|
||||
|
||||
AC_SUBST([DSOFLAGS])
|
||||
AC_SUBST([OPTIM])
|
||||
|
||||
|
||||
dnl Standard programs...
|
||||
AC_PROG_CC
|
||||
AC_PROG_RANLIB
|
||||
AC_PATH_PROG([AR], [ar])
|
||||
AC_PATH_PROGS([CODE_SIGN], [codesign true])
|
||||
AC_PATH_PROG([MKDIR], [mkdir])
|
||||
AC_PATH_PROG([RM], [rm])
|
||||
AC_PATH_PROG([RMDIR], [rmdir])
|
||||
AC_PATH_PROG([LN], [ln])
|
||||
|
||||
|
||||
dnl Figure out the correct "ar" command flags...
|
||||
AS_IF([test "$ac_cv_prog_ranlib" = ":"], [
|
||||
ARFLAGS="crs"
|
||||
], [
|
||||
ARFLAGS="cr"
|
||||
])
|
||||
AC_SUBST([ARFLAGS])
|
||||
|
||||
|
||||
dnl install-sh
|
||||
AC_MSG_CHECKING([for install-sh script])
|
||||
INSTALL="$(pwd)/install-sh"
|
||||
AC_SUBST([INSTALL])
|
||||
AC_MSG_RESULT([using $INSTALL])
|
||||
|
||||
|
||||
dnl Check for pkg-config, which is used for some other tests later on...
|
||||
AC_PATH_TOOL([PKGCONFIG], [pkg-config])
|
||||
|
||||
PKGCONFIG_CFLAGS="-I\${includedir}"
|
||||
PKGCONFIG_LIBS="-L\${libdir} -lpdfio"
|
||||
PKGCONFIG_LIBS_PRIVATE="-lm"
|
||||
PKGCONFIG_REQUIRES="zlib"
|
||||
AC_SUBST([PKGCONFIG_CFLAGS])
|
||||
AC_SUBST([PKGCONFIG_LIBS])
|
||||
AC_SUBST([PKGCONFIG_LIBS_PRIVATE])
|
||||
AC_SUBST([PKGCONFIG_REQUIRES])
|
||||
|
||||
|
||||
dnl ZLIB
|
||||
AC_MSG_CHECKING([for zlib via pkg-config])
|
||||
AS_IF([$PKCONFIG --exists zlib], [
|
||||
AC_MSG_RESULT([yes])
|
||||
LIBS="$($PKGCONFIG --libs zlib) $LIBS"
|
||||
CPPFLAGS="$($PKGCONFIG --cflags zlib) $CPPFLAGS"
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
AC_CHECK_HEADER([zlib.h])
|
||||
AC_CHECK_LIB([z], [inflateCopy])
|
||||
|
||||
AS_IF([test x$ac_cv_header_zlib_h != xyes -o x$ac_cv_lib_z_inflateCopy != xyes], [
|
||||
AC_MSG_ERROR([Sorry, this software requires zlib 1.1 or higher.])
|
||||
])
|
||||
|
||||
PKGCONFIG_LIBS_PRIVATE="-lz $PKGCONFIG_LIBS_PRIVATE"
|
||||
])
|
||||
|
||||
|
||||
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]))
|
||||
|
||||
AS_IF([test x$enable_shared = xyes], [
|
||||
AS_IF([test "$host_os_name" = darwin], [
|
||||
LIBPDFIO="libpdfio.1.dylib"
|
||||
], [
|
||||
LIBPDFIO="libpdfio.so.1"
|
||||
])
|
||||
|
||||
AS_IF([test x$enable_static != xno], [
|
||||
LIBPDFIO_STATIC="libpdfio.a"
|
||||
], [
|
||||
LIBPDFIO_STATIC=""
|
||||
])
|
||||
], [
|
||||
LIBPDFIO="libpdfio.a"
|
||||
LIBPDFIO_STATIC=""
|
||||
PKGCONFIG_LIBS="$PKGCONFIG_LIBS $PKGCONFIG_LIBS_PRIVATE"
|
||||
PKGCONFIG_LIBS_PRIVATE=""
|
||||
])
|
||||
|
||||
AC_SUBST([LIBPDFIO])
|
||||
AC_SUBST([LIBPDFIO_STATIC])
|
||||
|
||||
|
||||
dnl Extra compiler options...
|
||||
AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [turn on debugging, default=no]))
|
||||
AC_ARG_ENABLE([maintainer], AS_HELP_STRING([--enable-maintainer], [turn on maintainer mode, default=no]))
|
||||
AC_ARG_ENABLE([sanitizer], AS_HELP_STRING([--enable-sanitizer], [build with AddressSanitizer, default=no]))
|
||||
|
||||
AS_IF([test x$enable_debug = xyes], [
|
||||
OPTIM="$OPTIM -g"
|
||||
CSFLAGS=""
|
||||
], [
|
||||
OPTIM="$OPTIM -g -Os"
|
||||
CSFLAGS="-o runtime"
|
||||
])
|
||||
|
||||
AC_SUBST([CSFLAGS])
|
||||
|
||||
WARNINGS=""
|
||||
AC_SUBST([WARNINGS])
|
||||
|
||||
AS_IF([test -n "$GCC"], [
|
||||
AS_IF([test x$enable_sanitizer = xyes], [
|
||||
# Use -fsanitize=address with debugging...
|
||||
OPTIM="$OPTIM -fsanitize=address"
|
||||
], [
|
||||
# Otherwise use the Fortify enhancements to catch any unbounded
|
||||
# string operations...
|
||||
CPPFLAGS="$CPPFLAGS -D_FORTIFY_SOURCE=2"
|
||||
])
|
||||
|
||||
dnl Show all standard warnings + unused variables when compiling...
|
||||
WARNINGS="-Wall -Wunused"
|
||||
|
||||
dnl Drop some not-useful/unreliable warnings...
|
||||
for warning in char-subscripts format-truncation format-y2k switch unused-result; do
|
||||
AC_MSG_CHECKING([whether compiler supports -Wno-$warning])
|
||||
|
||||
OLDCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wno-$warning -Werror"
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], [
|
||||
AC_MSG_RESULT(yes)
|
||||
WARNINGS="$WARNINGS -Wno-$warning"
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
|
||||
CFLAGS="$OLDCFLAGS"
|
||||
done
|
||||
|
||||
dnl Maintainer mode enables -Werror...
|
||||
AS_IF([test x$enable_maintainer = xyes], [
|
||||
WARNINGS="$WARNINGS -Werror -Wno-error=deprecated"
|
||||
])
|
||||
|
||||
dnl See if PIE options are supported...
|
||||
AC_MSG_CHECKING(whether compiler supports -fPIE)
|
||||
OLDCFLAGS="$CFLAGS"
|
||||
AS_CASE(["$host_os_name"],
|
||||
[darwin*], [
|
||||
CFLAGS="$CFLAGS -fPIC -fPIE -Wl,-pie"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[
|
||||
OLDCFLAGS="-fPIC $OLDCFLAGS"
|
||||
LDFLAGS="-fPIE -Wl,-pie $LDFLAGS"
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
], [*], [
|
||||
CFLAGS="$CFLAGS -fPIC -fPIE -pie"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[
|
||||
OLDCFLAGS="-fPIC $OLDCFLAGS"
|
||||
LDFLAGS="-fPIE -pie $LDFLAGS"
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
CFLAGS="$OLDCFLAGS"
|
||||
|
||||
dnl OS-specific compiler options...
|
||||
AC_MSG_CHECKING([for OS-specific compiler options])
|
||||
AS_CASE(["$host_os_name"], [linux*], [
|
||||
# Make sure we get the full set of 64-bit Linux APIs from the headers...
|
||||
CPPFLAGS="$CPPFLAGS -D__USE_MISC -D_GNU_SOURCE -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64"
|
||||
|
||||
# Mark read-only sections as relocatable to random addresses...
|
||||
LDFLAGS="$LDFLAGS -Wl,-z,relro,-z,now"
|
||||
|
||||
AC_MSG_RESULT([-D__USE_MISC -D_GNU_SOURCE -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 -Wl,-z,relro,-z,now])
|
||||
], [darwin*], [
|
||||
# When not building for debug, target macOS 11 or later, "universal"
|
||||
# binaries when possible...
|
||||
AS_IF([echo "$CPPFLAGS $CFLAGS $LDFLAGS $OPTIM" | grep -q "\\-arch "], [
|
||||
# Don't add architecture/min-version flags if they are already present
|
||||
AC_MSG_RESULT([none])
|
||||
], [echo "$CPPFLAGS $CFLAGS $LDFLAGS $OPTIM" | grep -q "\\-mmacosx-version-"], [
|
||||
# Don't add architecture/min-version flags if they are already present
|
||||
AC_MSG_RESULT([none])
|
||||
], [test "$host_os_version" -ge 200 -a x$enable_debug != xyes], [
|
||||
# macOS 11.0 and higher support the Apple Silicon (arm64) CPUs
|
||||
OPTIM="$OPTIM -mmacosx-version-min=11.0 -arch x86_64 -arch arm64"
|
||||
AC_MSG_RESULT([-mmacosx-version-min=11.0 -arch x86_64 -arch arm64])
|
||||
], [
|
||||
# Don't add architecture/min-version flags if debug enabled
|
||||
AC_MSG_RESULT([none])
|
||||
])
|
||||
], [*], [
|
||||
AC_MSG_RESULT([none])
|
||||
])
|
||||
])
|
||||
|
||||
|
||||
dnl Extra linker options...
|
||||
AC_ARG_WITH([dsoflags], AS_HELP_STRING([--with-dsoflags=...], [Specify additional DSOFLAGS]), [
|
||||
DSOFLAGS="$withval $DSOFLAGS"
|
||||
])
|
||||
AC_ARG_WITH([ldflags], AS_HELP_STRING([--with-ldflags=...], [Specify additional LDFLAGS]), [
|
||||
LDFLAGS="$withval $LDFLAGS"
|
||||
])
|
||||
|
||||
|
||||
dnl Generate the Makefile and pkg-config file...
|
||||
AC_CONFIG_FILES([Makefile pdfio.pc])
|
||||
AC_OUTPUT
|
79
doc/pdfio.3
79
doc/pdfio.3
@ -1,4 +1,4 @@
|
||||
.TH pdfio 3 "pdf read/write library" "2023-10-06" "pdf read/write library"
|
||||
.TH pdfio 3 "pdf read/write library" "2023-12-05" "pdf read/write library"
|
||||
.SH NAME
|
||||
pdfio \- pdf read/write library
|
||||
.SH Introduction
|
||||
@ -1774,6 +1774,20 @@ bool pdfioContentTextEnd (
|
||||
pdfio_stream_t *st
|
||||
);
|
||||
.fi
|
||||
.SS pdfioContentTextMeasure
|
||||
Measure a text string and return its width.
|
||||
.PP
|
||||
.nf
|
||||
double pdfioContentTextMeasure (
|
||||
pdfio_obj_t *font,
|
||||
const char *s,
|
||||
double size
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function measures the given text string "s" and returns its width based
|
||||
on "size". The text string must always use the UTF-8 (Unicode) encoding but
|
||||
any control characters (such as newlines) are ignored.
|
||||
.SS pdfioContentTextMoveLine
|
||||
Move to the next line and offset.
|
||||
.PP
|
||||
@ -1794,14 +1808,49 @@ bool pdfioContentTextMoveTo (
|
||||
double ty
|
||||
);
|
||||
.fi
|
||||
.SS pdfioContentTextNextLine
|
||||
.SS pdfioContentTextNewLine
|
||||
Move to the next line.
|
||||
.PP
|
||||
.nf
|
||||
bool pdfioContentTextNextLine (
|
||||
bool pdfioContentTextNewLine (
|
||||
pdfio_stream_t *st
|
||||
);
|
||||
.fi
|
||||
.SS pdfioContentTextNewLineShow
|
||||
Move to the next line and show text.
|
||||
.PP
|
||||
.nf
|
||||
bool pdfioContentTextNewLineShow (
|
||||
pdfio_stream_t *st,
|
||||
double ws,
|
||||
double cs,
|
||||
bool unicode,
|
||||
const char *s
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function moves to the next line and then shows some text with optional
|
||||
word and character spacing in a PDF content stream. The "unicode" argument
|
||||
specifies that the current font maps to full Unicode. The "s" argument
|
||||
specifies a UTF-8 encoded string.
|
||||
.SS pdfioContentTextNewLineShowf
|
||||
Show formatted text.
|
||||
.PP
|
||||
.nf
|
||||
bool pdfioContentTextNewLineShowf (
|
||||
pdfio_stream_t *st,
|
||||
double ws,
|
||||
double cs,
|
||||
bool unicode,
|
||||
const char *format,
|
||||
...
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function moves to the next line and shows some formatted text with
|
||||
optional word and character spacing in a PDF content stream. The "unicode"
|
||||
argument specifies that the current font maps to full Unicode. The "format"
|
||||
argument specifies a UTF-8 encoded \fBprintf\fR-style format string.
|
||||
.SS pdfioContentTextShow
|
||||
Show text.
|
||||
.PP
|
||||
@ -2276,6 +2325,18 @@ Note: Currently PNG support is limited to grayscale, RGB, or indexed files
|
||||
without interlacing or alpha. Transparency (masking) based on color/index
|
||||
.IP 5
|
||||
is supported.
|
||||
.SS pdfioFileCreateNumberObj
|
||||
Create a new object in a PDF file containing a number.
|
||||
.PP
|
||||
.nf
|
||||
pdfio_obj_t * pdfioFileCreateNumberObj (
|
||||
pdfio_file_t *pdf,
|
||||
double number
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function creates a new object with a number value in a PDF file.
|
||||
You must call \fIpdfioObjClose\fR to write the object to the file.
|
||||
.SS pdfioFileCreateObj
|
||||
Create a new object in a PDF file.
|
||||
.PP
|
||||
@ -2340,6 +2401,18 @@ pdfio_stream_t * pdfioFileCreatePage (
|
||||
pdfio_dict_t *dict
|
||||
);
|
||||
.fi
|
||||
.SS pdfioFileCreateStringObj
|
||||
Create a new object in a PDF file containing a string.
|
||||
.PP
|
||||
.nf
|
||||
pdfio_obj_t * pdfioFileCreateStringObj (
|
||||
pdfio_file_t *pdf,
|
||||
const char *string
|
||||
);
|
||||
.fi
|
||||
.PP
|
||||
This function creates a new object with a string value in a PDF file.
|
||||
You must call \fIpdfioObjClose\fR to write the object to the file.
|
||||
.SS pdfioFileCreateTemporary
|
||||
|
||||
.PP
|
||||
|
124
doc/pdfio.html
124
doc/pdfio.html
@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<title>PDFio Programming Manual v1.1.2</title>
|
||||
<title>PDFio Programming Manual v1.2.0</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|
||||
<meta name="generator" content="codedoc v3.7">
|
||||
<meta name="author" content="Michael R Sweet">
|
||||
<meta name="language" content="en-US">
|
||||
<meta name="copyright" content="Copyright © 2021-2023 by Michael R Sweet">
|
||||
<meta name="version" content="1.1.2">
|
||||
<meta name="version" content="1.2.0">
|
||||
<style type="text/css"><!--
|
||||
body {
|
||||
background: white;
|
||||
@ -245,7 +245,7 @@ span.string {
|
||||
<body>
|
||||
<div class="header">
|
||||
<p><img class="title" src="pdfio-512.png"></p>
|
||||
<h1 class="title">PDFio Programming Manual v1.1.2</h1>
|
||||
<h1 class="title">PDFio Programming Manual v1.2.0</h1>
|
||||
<p>Michael R Sweet</p>
|
||||
<p>Copyright © 2021-2023 by Michael R Sweet</p>
|
||||
</div>
|
||||
@ -342,9 +342,12 @@ span.string {
|
||||
<li><a href="#pdfioContentStroke">pdfioContentStroke</a></li>
|
||||
<li><a href="#pdfioContentTextBegin">pdfioContentTextBegin</a></li>
|
||||
<li><a href="#pdfioContentTextEnd">pdfioContentTextEnd</a></li>
|
||||
<li><a href="#pdfioContentTextMeasure">pdfioContentTextMeasure</a></li>
|
||||
<li><a href="#pdfioContentTextMoveLine">pdfioContentTextMoveLine</a></li>
|
||||
<li><a href="#pdfioContentTextMoveTo">pdfioContentTextMoveTo</a></li>
|
||||
<li><a href="#pdfioContentTextNextLine">pdfioContentTextNextLine</a></li>
|
||||
<li><a href="#pdfioContentTextNewLine">pdfioContentTextNewLine</a></li>
|
||||
<li><a href="#pdfioContentTextNewLineShow">pdfioContentTextNewLineShow</a></li>
|
||||
<li><a href="#pdfioContentTextNewLineShowf">pdfioContentTextNewLineShowf</a></li>
|
||||
<li><a href="#pdfioContentTextShow">pdfioContentTextShow</a></li>
|
||||
<li><a href="#pdfioContentTextShowJustified">pdfioContentTextShowJustified</a></li>
|
||||
<li><a href="#pdfioContentTextShowf">pdfioContentTextShowf</a></li>
|
||||
@ -382,9 +385,11 @@ span.string {
|
||||
<li><a href="#pdfioFileCreateICCObjFromFile">pdfioFileCreateICCObjFromFile</a></li>
|
||||
<li><a href="#pdfioFileCreateImageObjFromData">pdfioFileCreateImageObjFromData</a></li>
|
||||
<li><a href="#pdfioFileCreateImageObjFromFile">pdfioFileCreateImageObjFromFile</a></li>
|
||||
<li><a href="#pdfioFileCreateNumberObj">pdfioFileCreateNumberObj</a></li>
|
||||
<li><a href="#pdfioFileCreateObj">pdfioFileCreateObj</a></li>
|
||||
<li><a href="#pdfioFileCreateOutput">pdfioFileCreateOutput</a></li>
|
||||
<li><a href="#pdfioFileCreatePage">pdfioFileCreatePage</a></li>
|
||||
<li><a href="#pdfioFileCreateStringObj">pdfioFileCreateStringObj</a></li>
|
||||
<li><a href="#pdfioFileCreateTemporary">pdfioFileCreateTemporary</a></li>
|
||||
<li><a href="#pdfioFileFindObj">pdfioFileFindObj</a></li>
|
||||
<li><a href="#pdfioFileGetAuthor">pdfioFileGetAuthor</a></li>
|
||||
@ -2005,6 +2010,25 @@ bool pdfioContentTextEnd(<a href="#pdfio_stream_t">pdfio_stream_t</a> *st);</p>
|
||||
</tbody></table>
|
||||
<h4 class="returnvalue">Return Value</h4>
|
||||
<p class="description"><code>true</code> on success, <code>false</code> on failure</p>
|
||||
<h3 class="function"><a id="pdfioContentTextMeasure">pdfioContentTextMeasure</a></h3>
|
||||
<p class="description">Measure a text string and return its width.</p>
|
||||
<p class="code">
|
||||
double pdfioContentTextMeasure(<a href="#pdfio_obj_t">pdfio_obj_t</a> *font, const char *s, double size);</p>
|
||||
<h4 class="parameters">Parameters</h4>
|
||||
<table class="list"><tbody>
|
||||
<tr><th>font</th>
|
||||
<td class="description">Font object created by <a href="#pdfioFileCreateFontObjFromFile"><code>pdfioFileCreateFontObjFromFile</code></a></td></tr>
|
||||
<tr><th>s</th>
|
||||
<td class="description">UTF-8 string</td></tr>
|
||||
<tr><th>size</th>
|
||||
<td class="description">Font size/height</td></tr>
|
||||
</tbody></table>
|
||||
<h4 class="returnvalue">Return Value</h4>
|
||||
<p class="description">Width</p>
|
||||
<h4 class="discussion">Discussion</h4>
|
||||
<p class="discussion">This function measures the given text string "s" and returns its width based
|
||||
on "size". The text string must always use the UTF-8 (Unicode) encoding but
|
||||
any control characters (such as newlines) are ignored.</p>
|
||||
<h3 class="function"><a id="pdfioContentTextMoveLine">pdfioContentTextMoveLine</a></h3>
|
||||
<p class="description">Move to the next line and offset.</p>
|
||||
<p class="code">
|
||||
@ -2035,10 +2059,10 @@ bool pdfioContentTextMoveTo(<a href="#pdfio_stream_t">pdfio_stream_t</a> *st, do
|
||||
</tbody></table>
|
||||
<h4 class="returnvalue">Return Value</h4>
|
||||
<p class="description"><code>true</code> on success, <code>false</code> on failure</p>
|
||||
<h3 class="function"><a id="pdfioContentTextNextLine">pdfioContentTextNextLine</a></h3>
|
||||
<h3 class="function"><a id="pdfioContentTextNewLine">pdfioContentTextNewLine</a></h3>
|
||||
<p class="description">Move to the next line.</p>
|
||||
<p class="code">
|
||||
bool pdfioContentTextNextLine(<a href="#pdfio_stream_t">pdfio_stream_t</a> *st);</p>
|
||||
bool pdfioContentTextNewLine(<a href="#pdfio_stream_t">pdfio_stream_t</a> *st);</p>
|
||||
<h4 class="parameters">Parameters</h4>
|
||||
<table class="list"><tbody>
|
||||
<tr><th>st</th>
|
||||
@ -2046,6 +2070,56 @@ bool pdfioContentTextNextLine(<a href="#pdfio_stream_t">pdfio_stream_t</a> *st);
|
||||
</tbody></table>
|
||||
<h4 class="returnvalue">Return Value</h4>
|
||||
<p class="description"><code>true</code> on success, <code>false</code> on failure</p>
|
||||
<h3 class="function"><a id="pdfioContentTextNewLineShow">pdfioContentTextNewLineShow</a></h3>
|
||||
<p class="description">Move to the next line and show text.</p>
|
||||
<p class="code">
|
||||
bool pdfioContentTextNewLineShow(<a href="#pdfio_stream_t">pdfio_stream_t</a> *st, double ws, double cs, bool unicode, const char *s);</p>
|
||||
<h4 class="parameters">Parameters</h4>
|
||||
<table class="list"><tbody>
|
||||
<tr><th>st</th>
|
||||
<td class="description">Stream</td></tr>
|
||||
<tr><th>ws</th>
|
||||
<td class="description">Word spacing or <code>0.0</code> for none</td></tr>
|
||||
<tr><th>cs</th>
|
||||
<td class="description">Character spacing or <code>0.0</code> for none</td></tr>
|
||||
<tr><th>unicode</th>
|
||||
<td class="description">Unicode text?</td></tr>
|
||||
<tr><th>s</th>
|
||||
<td class="description">String to show</td></tr>
|
||||
</tbody></table>
|
||||
<h4 class="returnvalue">Return Value</h4>
|
||||
<p class="description"><code>true</code> on success, <code>false</code> on failure</p>
|
||||
<h4 class="discussion">Discussion</h4>
|
||||
<p class="discussion">This function moves to the next line and then shows some text with optional
|
||||
word and character spacing in a PDF content stream. The "unicode" argument
|
||||
specifies that the current font maps to full Unicode. The "s" argument
|
||||
specifies a UTF-8 encoded string.</p>
|
||||
<h3 class="function"><a id="pdfioContentTextNewLineShowf">pdfioContentTextNewLineShowf</a></h3>
|
||||
<p class="description">Show formatted text.</p>
|
||||
<p class="code">
|
||||
bool pdfioContentTextNewLineShowf(<a href="#pdfio_stream_t">pdfio_stream_t</a> *st, double ws, double cs, bool unicode, const char *format, ...);</p>
|
||||
<h4 class="parameters">Parameters</h4>
|
||||
<table class="list"><tbody>
|
||||
<tr><th>st</th>
|
||||
<td class="description">Stream</td></tr>
|
||||
<tr><th>ws</th>
|
||||
<td class="description">Word spacing or <code>0.0</code> for none</td></tr>
|
||||
<tr><th>cs</th>
|
||||
<td class="description">Character spacing or <code>0.0</code> for none</td></tr>
|
||||
<tr><th>unicode</th>
|
||||
<td class="description">Unicode text?</td></tr>
|
||||
<tr><th>format</th>
|
||||
<td class="description"><code>printf</code>-style format string</td></tr>
|
||||
<tr><th>...</th>
|
||||
<td class="description">Additional arguments as needed</td></tr>
|
||||
</tbody></table>
|
||||
<h4 class="returnvalue">Return Value</h4>
|
||||
<p class="description"><code>true</code> on success, <code>false</code> on failure</p>
|
||||
<h4 class="discussion">Discussion</h4>
|
||||
<p class="discussion">This function moves to the next line and shows some formatted text with
|
||||
optional word and character spacing in a PDF content stream. The "unicode"
|
||||
argument specifies that the current font maps to full Unicode. The "format"
|
||||
argument specifies a UTF-8 encoded <code>printf</code>-style format string.</p>
|
||||
<h3 class="function"><a id="pdfioContentTextShow">pdfioContentTextShow</a></h3>
|
||||
<p class="description">Show text.</p>
|
||||
<p class="code">
|
||||
@ -2105,9 +2179,9 @@ bool pdfioContentTextShowf(<a href="#pdfio_stream_t">pdfio_stream_t</a> *st, boo
|
||||
</tbody></table>
|
||||
<h4 class="returnvalue">Return Value</h4>
|
||||
<p class="description">Show formatted text.</p>
|
||||
<p class="discussion">This function shows some text in a PDF content stream. The "unicode" argument
|
||||
specifies that the current font maps to full Unicode. The "format" argument
|
||||
specifies a UTF-8 encoded <code>printf</code>-style format string.</p>
|
||||
<p class="discussion">This function shows some formatted text in a PDF content stream. The
|
||||
"unicode" argument specifies that the current font maps to full Unicode.
|
||||
The "format" argument specifies a UTF-8 encoded <code>printf</code>-style format string.</p>
|
||||
<h3 class="function"><a id="pdfioDictCopy">pdfioDictCopy</a></h3>
|
||||
<p class="description">Copy a dictionary to a PDF file.</p>
|
||||
<p class="code">
|
||||
@ -2699,6 +2773,22 @@ image on the page.<br>
|
||||
Note: Currently PNG support is limited to grayscale, RGB, or indexed files
|
||||
without interlacing or alpha. Transparency (masking) based on color/index
|
||||
is supported.</blockquote>
|
||||
<h3 class="function"><a id="pdfioFileCreateNumberObj">pdfioFileCreateNumberObj</a></h3>
|
||||
<p class="description">Create a new object in a PDF file containing a number.</p>
|
||||
<p class="code">
|
||||
<a href="#pdfio_obj_t">pdfio_obj_t</a> *pdfioFileCreateNumberObj(<a href="#pdfio_file_t">pdfio_file_t</a> *pdf, double number);</p>
|
||||
<h4 class="parameters">Parameters</h4>
|
||||
<table class="list"><tbody>
|
||||
<tr><th>pdf</th>
|
||||
<td class="description">PDF file</td></tr>
|
||||
<tr><th>number</th>
|
||||
<td class="description">Number value</td></tr>
|
||||
</tbody></table>
|
||||
<h4 class="returnvalue">Return Value</h4>
|
||||
<p class="description">New object</p>
|
||||
<h4 class="discussion">Discussion</h4>
|
||||
<p class="discussion">This function creates a new object with a number value in a PDF file.
|
||||
You must call <a href="#pdfioObjClose"><code>pdfioObjClose</code></a> to write the object to the file.</p>
|
||||
<h3 class="function"><a id="pdfioFileCreateObj">pdfioFileCreateObj</a></h3>
|
||||
<p class="description">Create a new object in a PDF file.</p>
|
||||
<p class="code">
|
||||
@ -2777,6 +2867,22 @@ stored as indirect object references.</blockquote>
|
||||
</tbody></table>
|
||||
<h4 class="returnvalue">Return Value</h4>
|
||||
<p class="description">Contents stream</p>
|
||||
<h3 class="function"><a id="pdfioFileCreateStringObj">pdfioFileCreateStringObj</a></h3>
|
||||
<p class="description">Create a new object in a PDF file containing a string.</p>
|
||||
<p class="code">
|
||||
<a href="#pdfio_obj_t">pdfio_obj_t</a> *pdfioFileCreateStringObj(<a href="#pdfio_file_t">pdfio_file_t</a> *pdf, const char *string);</p>
|
||||
<h4 class="parameters">Parameters</h4>
|
||||
<table class="list"><tbody>
|
||||
<tr><th>pdf</th>
|
||||
<td class="description">PDF file</td></tr>
|
||||
<tr><th>string</th>
|
||||
<td class="description">String</td></tr>
|
||||
</tbody></table>
|
||||
<h4 class="returnvalue">Return Value</h4>
|
||||
<p class="description">New object</p>
|
||||
<h4 class="discussion">Discussion</h4>
|
||||
<p class="discussion">This function creates a new object with a string value in a PDF file.
|
||||
You must call <a href="#pdfioObjClose"><code>pdfioObjClose</code></a> to write the object to the file.</p>
|
||||
<h3 class="function"><a id="pdfioFileCreateTemporary">pdfioFileCreateTemporary</a></h3>
|
||||
<p class="description"></p>
|
||||
<p class="code">
|
||||
|
232
install-sh
Executable file
232
install-sh
Executable file
@ -0,0 +1,232 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Install a program, script, or datafile.
|
||||
#
|
||||
# Copyright 2008-2012 by Apple Inc.
|
||||
#
|
||||
# This script is not compatible with BSD (or any other) install program, as it
|
||||
# allows owner and group changes to fail with a warning and makes sure that the
|
||||
# destination directory permissions are as specified - BSD install and the
|
||||
# original X11 install script did not change permissions of existing
|
||||
# directories. It also does not support the transform options since CUPS does
|
||||
# not use them...
|
||||
#
|
||||
# Original script from X11R5 (mit/util/scripts/install.sh)
|
||||
# Copyright 1991 by the Massachusetts Institute of Technology
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||
# documentation for any purpose is hereby granted without fee, provided that
|
||||
# the above copyright notice appear in all copies and that both that
|
||||
# copyright notice and this permission notice appear in supporting
|
||||
# documentation, and that the name of M.I.T. not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without specific,
|
||||
# written prior permission. M.I.T. makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
# Force umask to 022...
|
||||
umask 022
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
gzipprog="${GZIPPROG-gzip}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
|
||||
gzipcp() {
|
||||
# gzipcp from to
|
||||
$gzipprog -9 <"$1" >"$2"
|
||||
}
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c)
|
||||
instcmd="$cpprog"
|
||||
shift
|
||||
continue
|
||||
;;
|
||||
|
||||
-d)
|
||||
dir_arg=true
|
||||
shift
|
||||
continue
|
||||
;;
|
||||
|
||||
-m)
|
||||
chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue
|
||||
;;
|
||||
|
||||
-o)
|
||||
chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue
|
||||
;;
|
||||
|
||||
-g)
|
||||
chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue
|
||||
;;
|
||||
|
||||
-s)
|
||||
stripcmd="$stripprog"
|
||||
shift
|
||||
continue
|
||||
;;
|
||||
|
||||
-z)
|
||||
instcmd="gzipcp"
|
||||
shift
|
||||
continue
|
||||
;;
|
||||
|
||||
*)
|
||||
if [ x"$src" = x ]; then
|
||||
src="$1"
|
||||
else
|
||||
dst="$1"
|
||||
fi
|
||||
shift
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]; then
|
||||
echo "install-sh: No input file specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst="$src"
|
||||
src=""
|
||||
|
||||
if [ -d "$dst" ]; then
|
||||
instcmd=:
|
||||
else
|
||||
instcmd=$mkdirprog
|
||||
fi
|
||||
else
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if [ ! -f "$src" -a ! -d "$src" ]; then
|
||||
echo "install: $src does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]; then
|
||||
echo "install: No destination specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename.
|
||||
if [ -d "$dst" ]; then
|
||||
dst="$dst/`basename $src`"
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir="`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`"
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# This part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
|
||||
oIFS="${IFS}"
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS="${oIFS}"
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp="${pathcomp}${1}"
|
||||
shift
|
||||
|
||||
if [ ! -d "${pathcomp}" ]; then $doit $mkdirprog "${pathcomp}"; fi
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
# Make a directory...
|
||||
$doit $instcmd $dst || exit 1
|
||||
|
||||
# Allow chown/chgrp to fail, but log a warning
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst || echo "warning: Unable to change owner of $dst!"; fi
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst || echo "warning: Unable to change group of $dst!"; fi
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst || exit 1; fi
|
||||
else
|
||||
# Install a file...
|
||||
dstfile="`basename $dst`"
|
||||
|
||||
# Check the destination file - for libraries just use the "-x" option
|
||||
# to strip...
|
||||
case "$dstfile" in
|
||||
*.a | *.dylib | *.sl | *.sl.* | *.so | *.so.*)
|
||||
stripopt="-x"
|
||||
;;
|
||||
*)
|
||||
stripopt=""
|
||||
;;
|
||||
esac
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
dsttmp="$dstdir/#inst.$$#"
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
$doit $instcmd $src $dsttmp || exit 1
|
||||
|
||||
# Update permissions and strip as needed, then move to the final name.
|
||||
# If the chmod, strip, rm, or mv commands fail, remove the installed
|
||||
# file...
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $stripopt "$dsttmp" || echo "warning: Unable to strip $dst!"; fi
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp" || echo "warning: Unable to change owner of $dst!"; fi
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp" || echo "warning: Unable to change group of $dst!"; fi
|
||||
|
||||
trap "rm -f ${dsttmp}" 0 &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; fi &&
|
||||
$doit $rmcmd -f "$dstdir/$dstfile" &&
|
||||
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
|
||||
fi
|
||||
|
||||
exit 0
|
@ -375,9 +375,9 @@ _pdfioFileSeek(pdfio_file_t *pdf, // I - PDF file
|
||||
if (whence != SEEK_END && offset >= pdf->bufpos && offset < (pdf->bufpos + pdf->bufend - pdf->buffer))
|
||||
{
|
||||
// Yes, seek within existing buffer...
|
||||
pdf->bufptr = pdf->buffer + offset - pdf->bufpos;
|
||||
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, bufend=%p\n", pdf->buffer, pdf->bufptr, 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);
|
||||
}
|
||||
|
||||
|
437
pdfio-content.c
437
pdfio-content.c
@ -7,10 +7,6 @@
|
||||
// information.
|
||||
//
|
||||
|
||||
//
|
||||
// Include necessary headers...
|
||||
//
|
||||
|
||||
#include "pdfio-private.h"
|
||||
#include "pdfio-content.h"
|
||||
#include "ttf.h"
|
||||
@ -1064,6 +1060,104 @@ pdfioContentTextEnd(pdfio_stream_t *st) // I - Stream
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioContentTextMeasure()' - Measure a text string and return its width.
|
||||
//
|
||||
// This function measures the given text string "s" and returns its width based
|
||||
// on "size". The text string must always use the UTF-8 (Unicode) encoding but
|
||||
// any control characters (such as newlines) are ignored.
|
||||
//
|
||||
|
||||
double // O - Width
|
||||
pdfioContentTextMeasure(
|
||||
pdfio_obj_t *font, // I - Font object created by @link pdfioFileCreateFontObjFromFile@
|
||||
const char *s, // I - UTF-8 string
|
||||
double size) // I - Font size/height
|
||||
{
|
||||
const char *subtype; // Font sub-type
|
||||
ttf_t *ttf = (ttf_t *)_pdfioObjGetExtension(font);
|
||||
// TrueType font data
|
||||
ttf_rect_t extents; // Text extents
|
||||
int ch; // Unicode character
|
||||
char temp[1024], // Temporary string
|
||||
*tempptr; // Pointer into temporary string
|
||||
|
||||
|
||||
if ((subtype = pdfioObjGetSubtype(font)) == NULL || strcmp(subtype, "Type0"))
|
||||
{
|
||||
// Map non-CP1282 characters to '?', everything else as-is...
|
||||
tempptr = temp;
|
||||
|
||||
while (*s && tempptr < (temp + sizeof(temp) - 3))
|
||||
{
|
||||
if ((*s & 0xe0) == 0xc0)
|
||||
{
|
||||
// Two-byte UTF-8
|
||||
ch = ((s[0] & 0x1f) << 6) | (s[1] & 0x3f);
|
||||
s += 2;
|
||||
}
|
||||
else if ((*s & 0xf0) == 0xe0)
|
||||
{
|
||||
// Three-byte UTF-8
|
||||
ch = ((s[0] & 0x0f) << 12) | ((s[1] & 0x3f) << 6) | (s[2] & 0x3f);
|
||||
s += 3;
|
||||
}
|
||||
else if ((*s & 0xf8) == 0xf0)
|
||||
{
|
||||
// Four-byte UTF-8
|
||||
ch = ((s[0] & 0x07) << 18) | ((s[1] & 0x3f) << 12) | ((s[2] & 0x3f) << 6) | (s[3] & 0x3f);
|
||||
s += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
ch = *s++;
|
||||
}
|
||||
|
||||
if (ch > 255)
|
||||
{
|
||||
// Try mapping from Unicode to CP1252...
|
||||
size_t i; // Looping var
|
||||
|
||||
for (i = 0; i < (sizeof(_pdfio_cp1252) / sizeof(_pdfio_cp1252[0])); i ++)
|
||||
{
|
||||
if (ch == _pdfio_cp1252[i])
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= (sizeof(_pdfio_cp1252) / sizeof(_pdfio_cp1252[0])))
|
||||
ch = '?'; // Unsupported chars map to ?
|
||||
}
|
||||
|
||||
if (ch < 128)
|
||||
{
|
||||
// ASCII
|
||||
*tempptr++ = ch;
|
||||
}
|
||||
else if (ch < 2048)
|
||||
{
|
||||
// 2-byte UTF-8
|
||||
*tempptr++ = 0xc0 | ((ch >> 6) & 0x1f);
|
||||
*tempptr++ = 0x80 | (ch & 0x3f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 3-byte UTF-8
|
||||
*tempptr++ = 0xe0 | ((ch >> 12) & 0x0f);
|
||||
*tempptr++ = 0x80 | ((ch >> 6) & 0x3f);
|
||||
*tempptr++ = 0x80 | (ch & 0x3f);
|
||||
}
|
||||
}
|
||||
|
||||
*tempptr = '\0';
|
||||
s = temp;
|
||||
}
|
||||
|
||||
ttfGetExtents(ttf, size, s, &extents);
|
||||
|
||||
return (extents.right - extents.left);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioContentTextMoveLine()' - Move to the next line and offset.
|
||||
//
|
||||
@ -1093,17 +1187,97 @@ pdfioContentTextMoveTo(
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioContentTextNextLine()' - Move to the next line.
|
||||
// 'pdfioContentTextNewLine()' - Move to the next line.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
pdfioContentTextNextLine(
|
||||
pdfioContentTextNewLine(
|
||||
pdfio_stream_t *st) // I - Stream
|
||||
{
|
||||
return (pdfioStreamPuts(st, "T*\n"));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioContentTextNewLineShow()' - Move to the next line and show text.
|
||||
//
|
||||
// This function moves to the next line and then shows some text with optional
|
||||
// word and character spacing in a PDF content stream. The "unicode" argument
|
||||
// specifies that the current font maps to full Unicode. The "s" argument
|
||||
// specifies a UTF-8 encoded string.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
pdfioContentTextNewLineShow(
|
||||
pdfio_stream_t *st, // I - Stream
|
||||
double ws, // I - Word spacing or `0.0` for none
|
||||
double cs, // I - Character spacing or `0.0` for none
|
||||
bool unicode, // I - Unicode text?
|
||||
const char *s) // I - String to show
|
||||
{
|
||||
bool newline = false; // New line?
|
||||
char op; // Text operator
|
||||
|
||||
|
||||
// Write word and/or character spacing as needed...
|
||||
if (ws > 0.0 || cs > 0.0)
|
||||
{
|
||||
// Use " operator to show text with word and character spacing...
|
||||
if (!pdfioStreamPrintf(st, "%g %g", ws, cs))
|
||||
return (false);
|
||||
|
||||
op = '\"';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use ' operator to show text with the defaults...
|
||||
op = '\'';
|
||||
}
|
||||
|
||||
// Write the string...
|
||||
if (!write_string(st, unicode, s, &newline))
|
||||
return (false);
|
||||
|
||||
// Draw it...
|
||||
if (newline)
|
||||
return (pdfioStreamPrintf(st, "%c T*\n", op));
|
||||
else
|
||||
return (pdfioStreamPrintf(st, "%c\n", op));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioContentTextNewLineShowf()' - Show formatted text.
|
||||
//
|
||||
// This function moves to the next line and shows some formatted text with
|
||||
// optional word and character spacing in a PDF content stream. The "unicode"
|
||||
// argument specifies that the current font maps to full Unicode. The "format"
|
||||
// argument specifies a UTF-8 encoded `printf`-style format string.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
pdfioContentTextNewLineShowf(
|
||||
pdfio_stream_t *st, // I - Stream
|
||||
double ws, // I - Word spacing or `0.0` for none
|
||||
double cs, // I - Character spacing or `0.0` for none
|
||||
bool unicode, // I - Unicode text?
|
||||
const char *format, // I - `printf`-style format string
|
||||
...) // I - Additional arguments as needed
|
||||
{
|
||||
char buffer[8192]; // Text buffer
|
||||
va_list ap; // Argument pointer
|
||||
|
||||
|
||||
// Format the string...
|
||||
va_start(ap, format);
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
// Show it...
|
||||
return (pdfioContentTextNewLineShow(st, ws, cs, unicode, buffer));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioContentTextShow()' - Show text.
|
||||
//
|
||||
@ -1136,9 +1310,9 @@ pdfioContentTextShow(
|
||||
//
|
||||
// 'pdfioContentTextShowf()' - Show formatted text.
|
||||
//
|
||||
// This function shows some text in a PDF content stream. The "unicode" argument
|
||||
// specifies that the current font maps to full Unicode. The "format" argument
|
||||
// specifies a UTF-8 encoded `printf`-style format string.
|
||||
// This function shows some formatted text in a PDF content stream. The
|
||||
// "unicode" argument specifies that the current font maps to full Unicode.
|
||||
// The "format" argument specifies a UTF-8 encoded `printf`-style format string.
|
||||
//
|
||||
|
||||
bool
|
||||
@ -1289,13 +1463,13 @@ pdfioFileCreateFontObjFromFile(
|
||||
pdfio_dict_t *dict, // Font dictionary
|
||||
*desc, // Font descriptor
|
||||
*file; // Font file dictionary
|
||||
pdfio_obj_t *obj, // Font object
|
||||
pdfio_obj_t *obj = NULL, // Font object
|
||||
*desc_obj, // Font descriptor object
|
||||
*file_obj; // Font file object
|
||||
const char *basefont; // Base font name
|
||||
pdfio_array_t *bbox; // Font bounding box array
|
||||
pdfio_stream_t *st; // Font stream
|
||||
int fd; // File
|
||||
int fd = -1; // File
|
||||
unsigned char buffer[16384]; // Read buffer
|
||||
ssize_t bytes; // Bytes read
|
||||
|
||||
@ -1324,48 +1498,32 @@ pdfioFileCreateFontObjFromFile(
|
||||
|
||||
// Create the font file dictionary and object...
|
||||
if ((file = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
pdfioDictSetName(file, "Filter", "FlateDecode");
|
||||
|
||||
if ((file_obj = pdfioFileCreateObj(pdf, file)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
if ((st = pdfioObjCreateStream(file_obj, PDFIO_FILTER_FLATE)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
|
||||
{
|
||||
if (!pdfioStreamWrite(st, buffer, (size_t)bytes))
|
||||
{
|
||||
ttfDelete(font);
|
||||
close(fd);
|
||||
pdfioStreamClose(st);
|
||||
return (NULL);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
fd = -1;
|
||||
pdfioStreamClose(st);
|
||||
|
||||
// Create the font descriptor dictionary and object...
|
||||
if ((bbox = pdfioArrayCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
ttfGetBounds(font, &bounds);
|
||||
|
||||
@ -1375,10 +1533,7 @@ pdfioFileCreateFontObjFromFile(
|
||||
pdfioArrayAppendNumber(bbox, bounds.top);
|
||||
|
||||
if ((desc = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
basefont = pdfioStringCreate(pdf, ttfGetPostScriptName(font));
|
||||
|
||||
@ -1397,56 +1552,64 @@ pdfioFileCreateFontObjFromFile(
|
||||
pdfioDictSetNumber(desc, "StemV", ttfGetWeight(font) / 4 + 25);
|
||||
|
||||
if ((desc_obj = pdfioFileCreateObj(pdf, desc)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
pdfioObjClose(desc_obj);
|
||||
|
||||
if (unicode)
|
||||
{
|
||||
// Unicode (CID) font...
|
||||
pdfio_dict_t *cid2gid; // CIDToGIDMap dictionary
|
||||
pdfio_obj_t *cid2gid_obj; // CIDToGIDMap object
|
||||
pdfio_dict_t *cid2gid, // CIDToGIDMap dictionary
|
||||
*to_unicode; // ToUnicode dictionary
|
||||
pdfio_obj_t *cid2gid_obj, // CIDToGIDMap object
|
||||
*to_unicode_obj;// ToUnicode object
|
||||
size_t i, // Looping var
|
||||
start, // Start character
|
||||
num_cmap; // Number of CMap entries
|
||||
const int *cmap; // CMap entries
|
||||
int min_glyph, // First glyph
|
||||
max_glyph; // Last glyph
|
||||
unsigned short glyphs[65536]; // Glyph to Unicode mapping
|
||||
unsigned char *bufptr, // Pointer into buffer
|
||||
*bufend; // End of buffer
|
||||
pdfio_dict_t *type2; // CIDFontType2 font dictionary
|
||||
pdfio_obj_t *type2_obj; // CIDFontType2 font object
|
||||
pdfio_array_t *descendants; // Decendant font list
|
||||
pdfio_dict_t *sidict; // CIDSystemInfo dictionary
|
||||
pdfio_array_t *w_array, // Width array
|
||||
*temp_array; // Temporary width sub-array
|
||||
int w0, w1; // Widths
|
||||
|
||||
// Create a CIDSystemInfo mapping to Adobe UCS2 v0 (Unicode)
|
||||
if ((sidict = pdfioDictCreate(pdf)) == NULL)
|
||||
goto done;
|
||||
|
||||
pdfioDictSetString(sidict, "Registry", "Adobe");
|
||||
pdfioDictSetString(sidict, "Ordering", "Identity");
|
||||
pdfioDictSetNumber(sidict, "Supplement", 0);
|
||||
|
||||
// Create a CIDToGIDMap object for the Unicode font...
|
||||
if ((cid2gid = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
#ifndef DEBUG
|
||||
pdfioDictSetName(cid2gid, "Filter", "FlateDecode");
|
||||
#endif // !DEBUG
|
||||
|
||||
if ((cid2gid_obj = pdfioFileCreateObj(pdf, cid2gid)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ((st = pdfioObjCreateStream(cid2gid_obj, PDFIO_FILTER_NONE)) == NULL)
|
||||
#else
|
||||
if ((st = pdfioObjCreateStream(cid2gid_obj, PDFIO_FILTER_FLATE)) == NULL)
|
||||
#endif // DEBUG
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
cmap = ttfGetCMap(font, &num_cmap);
|
||||
cmap = ttfGetCMap(font, &num_cmap);
|
||||
min_glyph = 65536;
|
||||
max_glyph = 0;
|
||||
memset(glyphs, 0, sizeof(glyphs));
|
||||
|
||||
PDFIO_DEBUG("pdfioFileCreateFontObjFromFile: num_cmap=%u\n", (unsigned)num_cmap);
|
||||
|
||||
@ -1464,6 +1627,12 @@ pdfioFileCreateFontObjFromFile(
|
||||
// Map to specified glyph...
|
||||
*bufptr++ = (unsigned char)(cmap[i] >> 8);
|
||||
*bufptr++ = (unsigned char)(cmap[i] & 255);
|
||||
|
||||
glyphs[cmap[i]] = i;
|
||||
if (cmap[i] < min_glyph)
|
||||
min_glyph = cmap[i];
|
||||
if (cmap[i] > max_glyph)
|
||||
max_glyph = cmap[i];
|
||||
}
|
||||
|
||||
if (bufptr >= bufend)
|
||||
@ -1472,8 +1641,7 @@ pdfioFileCreateFontObjFromFile(
|
||||
if (!pdfioStreamWrite(st, buffer, (size_t)(bufptr - buffer)))
|
||||
{
|
||||
pdfioStreamClose(st);
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
goto done;
|
||||
}
|
||||
|
||||
bufptr = buffer;
|
||||
@ -1486,30 +1654,102 @@ pdfioFileCreateFontObjFromFile(
|
||||
if (!pdfioStreamWrite(st, buffer, (size_t)(bufptr - buffer)))
|
||||
{
|
||||
pdfioStreamClose(st);
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
pdfioStreamClose(st);
|
||||
|
||||
// ToUnicode mapping object
|
||||
to_unicode = pdfioDictCreate(pdf);
|
||||
pdfioDictSetName(to_unicode, "Type", "CMap");
|
||||
pdfioDictSetName(to_unicode, "CMapName", "Adobe-Identity-UCS2");
|
||||
pdfioDictSetDict(to_unicode, "CIDSystemInfo", sidict);
|
||||
|
||||
#ifndef DEBUG
|
||||
pdfioDictSetName(to_unicode, "Filter", "FlateDecode");
|
||||
#endif // !DEBUG
|
||||
|
||||
if ((to_unicode_obj = pdfioFileCreateObj(pdf, to_unicode)) == NULL)
|
||||
goto done;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ((st = pdfioObjCreateStream(to_unicode_obj, PDFIO_FILTER_NONE)) == NULL)
|
||||
#else
|
||||
if ((st = pdfioObjCreateStream(to_unicode_obj, PDFIO_FILTER_FLATE)) == NULL)
|
||||
#endif // DEBUG
|
||||
goto done;
|
||||
|
||||
pdfioStreamPuts(st,
|
||||
"stream\n"
|
||||
"/CIDInit /ProcSet findresource begin\n"
|
||||
"12 dict begin\n"
|
||||
"begincmap\n"
|
||||
"/CIDSystemInfo<<\n"
|
||||
"/Registry (Adobe)\n"
|
||||
"/Ordering (UCS2)\n"
|
||||
"/Supplement 0\n"
|
||||
">> def\n"
|
||||
"/CMapName /Adobe-Identity-UCS2 def\n"
|
||||
"/CMapType 2 def\n"
|
||||
"1 begincodespacerange\n"
|
||||
"<0000> <FFFF>\n"
|
||||
"endcodespacerange\n"
|
||||
"1 beginbfrange\n"
|
||||
"<0000> <FFFF> <0000>\n"
|
||||
"endbfrange\n"
|
||||
"endcmap\n"
|
||||
"CMapName currentdict /CMap defineresource pop\n"
|
||||
"end\n"
|
||||
"end\n");
|
||||
|
||||
pdfioStreamClose(st);
|
||||
|
||||
// Create a CIDFontType2 dictionary for the Unicode font...
|
||||
if ((type2 = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
if ((sidict = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
// Width array
|
||||
if ((w_array = pdfioArrayCreate(pdf)) == NULL)
|
||||
goto done;
|
||||
|
||||
// CIDSystemInfo mapping to Adobe UCS2 v0 (Unicode)
|
||||
pdfioDictSetString(sidict, "Registry", "Adobe");
|
||||
pdfioDictSetString(sidict, "Ordering", "Identity-H");
|
||||
pdfioDictSetNumber(sidict, "Supplement", 0);
|
||||
for (start = 0, w0 = ttfGetWidth(font, 0), i = 1; i < 65536; start = i, w0 = w1, i ++)
|
||||
{
|
||||
while (i < 65536 && (w1 = ttfGetWidth(font, i)) == w0)
|
||||
i ++;
|
||||
|
||||
if ((i - start) > 1)
|
||||
{
|
||||
// Encode a repeating sequence...
|
||||
pdfioArrayAppendNumber(w_array, start);
|
||||
pdfioArrayAppendNumber(w_array, i - 1);
|
||||
pdfioArrayAppendNumber(w_array, w0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Encode a non-repeating sequence...
|
||||
pdfioArrayAppendNumber(w_array, start);
|
||||
|
||||
if ((temp_array = pdfioArrayCreate(pdf)) == NULL)
|
||||
goto done;
|
||||
|
||||
pdfioArrayAppendNumber(temp_array, w0);
|
||||
for (w0 = w1, i ++; i < 65536; w0 = w1, i ++)
|
||||
{
|
||||
if ((w1 = ttfGetWidth(font, i)) == w0 && i < 65535)
|
||||
break;
|
||||
|
||||
pdfioArrayAppendNumber(temp_array, w0);
|
||||
}
|
||||
|
||||
if (i == 65536)
|
||||
pdfioArrayAppendNumber(temp_array, w0);
|
||||
else
|
||||
i --;
|
||||
|
||||
pdfioArrayAppendArray(w_array, temp_array);
|
||||
}
|
||||
}
|
||||
|
||||
// Then the dictionary for the CID base font...
|
||||
pdfioDictSetName(type2, "Type", "Font");
|
||||
@ -1518,56 +1758,41 @@ pdfioFileCreateFontObjFromFile(
|
||||
pdfioDictSetDict(type2, "CIDSystemInfo", sidict);
|
||||
pdfioDictSetObj(type2, "CIDToGIDMap", cid2gid_obj);
|
||||
pdfioDictSetObj(type2, "FontDescriptor", desc_obj);
|
||||
pdfioDictSetArray(type2, "W", w_array);
|
||||
|
||||
if ((type2_obj = pdfioFileCreateObj(pdf, type2)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
pdfioObjClose(type2_obj);
|
||||
|
||||
// Create a Type 0 font object...
|
||||
if ((descendants = pdfioArrayCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
pdfioArrayAppendObj(descendants, type2_obj);
|
||||
|
||||
if ((dict = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
pdfioDictSetName(dict, "Type", "Font");
|
||||
pdfioDictSetName(dict, "Subtype", "Type0");
|
||||
pdfioDictSetName(dict, "BaseFont", basefont);
|
||||
pdfioDictSetArray(dict, "DescendantFonts", descendants);
|
||||
pdfioDictSetName(dict, "Encoding", "Identity-H");
|
||||
pdfioDictSetObj(dict, "ToUnicode", to_unicode_obj);
|
||||
|
||||
if ((obj = pdfioFileCreateObj(pdf, dict)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
pdfioObjClose(obj);
|
||||
if ((obj = pdfioFileCreateObj(pdf, dict)) != NULL)
|
||||
pdfioObjClose(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simple (CP1282 or custom encoding) 8-bit font...
|
||||
if (ttfGetMaxChar(font) >= 255 && !pdf->cp1252_obj && !create_cp1252(pdf))
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
// Create a TrueType font object...
|
||||
if ((dict = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
goto done;
|
||||
|
||||
pdfioDictSetName(dict, "Type", "Font");
|
||||
pdfioDictSetName(dict, "Subtype", "TrueType");
|
||||
@ -1577,16 +1802,16 @@ pdfioFileCreateFontObjFromFile(
|
||||
|
||||
pdfioDictSetObj(dict, "FontDescriptor", desc_obj);
|
||||
|
||||
if ((obj = pdfioFileCreateObj(pdf, dict)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pdfioObjClose(obj);
|
||||
if ((obj = pdfioFileCreateObj(pdf, dict)) != NULL)
|
||||
pdfioObjClose(obj);
|
||||
}
|
||||
|
||||
ttfDelete(font);
|
||||
done:
|
||||
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
|
||||
_pdfioObjSetExtension(obj, font, (_pdfio_extfree_t)ttfDelete);
|
||||
|
||||
return (obj);
|
||||
}
|
||||
@ -3000,7 +3225,7 @@ write_string(pdfio_stream_t *st, // I - Stream
|
||||
|
||||
|
||||
// Start the string...
|
||||
if (!pdfioStreamPuts(st, unicode ? "<FEFF" : "("))
|
||||
if (!pdfioStreamPuts(st, unicode ? "<" : "("))
|
||||
return (false);
|
||||
|
||||
// Loop through the string, handling UTF-8 as needed...
|
||||
|
@ -115,9 +115,12 @@ extern bool pdfioContentSetTextXScaling(pdfio_stream_t *st, double percent) _PD
|
||||
extern bool pdfioContentStroke(pdfio_stream_t *st) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextBegin(pdfio_stream_t *st) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextEnd(pdfio_stream_t *st) _PDFIO_PUBLIC;
|
||||
extern double pdfioContentTextMeasure(pdfio_obj_t *font, const char *s, double size) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextMoveLine(pdfio_stream_t *st, double tx, double ty) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextMoveTo(pdfio_stream_t *st, double tx, double ty) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextNextLine(pdfio_stream_t *st) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextNewLine(pdfio_stream_t *st) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextNewLineShow(pdfio_stream_t *st, double ws, double cs, bool unicode, const char *s) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextNewLineShowf(pdfio_stream_t *st, double ws, double cs, bool unicode, const char *format, ...) _PDFIO_PUBLIC _PDFIO_FORMAT(5,6);
|
||||
extern bool pdfioContentTextShow(pdfio_stream_t *st, bool unicode, const char *s) _PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextShowf(pdfio_stream_t *st, bool unicode, const char *format, ...) _PDFIO_PUBLIC _PDFIO_FORMAT(3,4);
|
||||
extern bool pdfioContentTextShowJustified(pdfio_stream_t *st, bool unicode, size_t num_fragments, const double *offsets, const char * const *fragments) _PDFIO_PUBLIC;
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Cryptographic support functions for PDFio.
|
||||
//
|
||||
// Copyright © 2021 by Michael R Sweet.
|
||||
// Copyright © 2021-2023 by Michael R Sweet.
|
||||
//
|
||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||
// information.
|
||||
@ -446,10 +446,18 @@ _pdfio_crypto_cb_t // O - Decryption callback or `NULL` for none
|
||||
|
||||
// Initialize the RC4 context using 40 bits of the digest...
|
||||
_pdfioCryptoRC4Init(&ctx->rc4, digest, 5);
|
||||
*ivlen = 0;
|
||||
return ((_pdfio_crypto_cb_t)_pdfioCryptoRC4Crypt);
|
||||
|
||||
case PDFIO_ENCRYPTION_RC4_128 :
|
||||
case PDFIO_ENCRYPTION_AES_128 :
|
||||
if (*ivlen < 16)
|
||||
{
|
||||
*ivlen = 0;
|
||||
_pdfioFileError(pdf, "Value too short for AES encryption.");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
case PDFIO_ENCRYPTION_RC4_128 :
|
||||
// Copy the key data for the MD5 hash.
|
||||
memcpy(data, pdf->file_key, sizeof(pdf->file_key));
|
||||
data[16] = (uint8_t)obj->number;
|
||||
|
71
pdfio-file.c
71
pdfio-file.c
@ -334,6 +334,32 @@ pdfioFileCreateArrayObj(
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioFileCreateNumberObj()' - Create a new object in a PDF file containing a number.
|
||||
//
|
||||
// This function creates a new object with a number value in a PDF file.
|
||||
// You must call @link pdfioObjClose@ to write the object to the file.
|
||||
//
|
||||
|
||||
pdfio_obj_t * // O - New object
|
||||
pdfioFileCreateNumberObj(
|
||||
pdfio_file_t *pdf, // I - PDF file
|
||||
double number) // I - Number value
|
||||
{
|
||||
_pdfio_value_t value; // Object value
|
||||
|
||||
|
||||
// Range check input...
|
||||
if (!pdf)
|
||||
return (NULL);
|
||||
|
||||
value.type = PDFIO_VALTYPE_NUMBER;
|
||||
value.value.number = number;
|
||||
|
||||
return (_pdfioFileCreateObj(pdf, NULL, &value));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioFileCreateObj()' - Create a new object in a PDF file.
|
||||
//
|
||||
@ -639,6 +665,32 @@ pdfioFileCreatePage(pdfio_file_t *pdf, // I - PDF file
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioFileCreateStringObj()' - Create a new object in a PDF file containing a string.
|
||||
//
|
||||
// This function creates a new object with a string value in a PDF file.
|
||||
// You must call @link pdfioObjClose@ to write the object to the file.
|
||||
//
|
||||
|
||||
pdfio_obj_t * // O - New object
|
||||
pdfioFileCreateStringObj(
|
||||
pdfio_file_t *pdf, // I - PDF file
|
||||
const char *string) // I - String
|
||||
{
|
||||
_pdfio_value_t value; // Object value
|
||||
|
||||
|
||||
// Range check input...
|
||||
if (!pdf)
|
||||
return (NULL);
|
||||
|
||||
value.type = PDFIO_VALTYPE_STRING;
|
||||
value.value.string = string;
|
||||
|
||||
return (_pdfioFileCreateObj(pdf, NULL, &value));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioFileCreateTemporary()' - Create a temporary PDF file.
|
||||
//
|
||||
@ -1514,6 +1566,7 @@ load_obj_stream(pdfio_obj_t *obj) // I - Object to load
|
||||
|
||||
// Skip offset
|
||||
_pdfioTokenGet(&tb, buffer, sizeof(buffer));
|
||||
PDFIO_DEBUG("load_obj_stream: %ld at offset %s\n", (long)number, buffer);
|
||||
}
|
||||
|
||||
if (!buffer[0])
|
||||
@ -1865,8 +1918,18 @@ load_xref(
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= num_sobjs && num_sobjs < (sizeof(sobjs) / sizeof(sobjs[0])))
|
||||
sobjs[num_sobjs ++] = (size_t)offset;
|
||||
if (i >= num_sobjs)
|
||||
{
|
||||
if (num_sobjs < (sizeof(sobjs) / sizeof(sobjs[0])))
|
||||
{
|
||||
sobjs[num_sobjs ++] = (size_t)offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
_pdfioFileError(pdf, "Too many object streams.");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!current)
|
||||
{
|
||||
@ -1914,12 +1977,12 @@ load_xref(
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strncmp(line, "xref", 4) && !line[4] || isspace(line[4] & 255))
|
||||
else if (!strncmp(line, "xref", 4) && (!line[4] || isspace(line[4] & 255)))
|
||||
{
|
||||
// Read the xref tables
|
||||
while (_pdfioFileGets(pdf, line, sizeof(line)))
|
||||
{
|
||||
if (!strncmp(line, "trailer", 7) && !line[7] || isspace(line[7] & 255))
|
||||
if (!strncmp(line, "trailer", 7) && (!line[7] || isspace(line[7] & 255)))
|
||||
break;
|
||||
else if (!line[0])
|
||||
continue;
|
||||
|
@ -7,10 +7,6 @@
|
||||
// information.
|
||||
//
|
||||
|
||||
//
|
||||
// Include necessary headers...
|
||||
//
|
||||
|
||||
#include "pdfio-private.h"
|
||||
|
||||
|
||||
@ -221,8 +217,13 @@ void
|
||||
_pdfioObjDelete(pdfio_obj_t *obj) // I - Object
|
||||
{
|
||||
if (obj)
|
||||
{
|
||||
pdfioStreamClose(obj->stream);
|
||||
|
||||
if (obj->datafree)
|
||||
(obj->datafree)(obj->data);
|
||||
}
|
||||
|
||||
free(obj);
|
||||
}
|
||||
|
||||
@ -267,6 +268,17 @@ pdfioObjGetDict(pdfio_obj_t *obj) // I - Object
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// '_pdfioObjGetExtension()' - Get the extension pointer for an object.
|
||||
//
|
||||
|
||||
void * // O - Extension data
|
||||
_pdfioObjGetExtension(pdfio_obj_t *obj) // I - Object
|
||||
{
|
||||
return (obj->data);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioObjGetGeneration()' - Get the object's generation number.
|
||||
//
|
||||
@ -498,6 +510,21 @@ pdfioObjOpenStream(pdfio_obj_t *obj, // I - Object
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// '_pdfioObjSetExtension()' - Set extension data for an object.
|
||||
//
|
||||
|
||||
void
|
||||
_pdfioObjSetExtension(
|
||||
pdfio_obj_t *obj, // I - Object
|
||||
void *data, // I - Data
|
||||
_pdfio_extfree_t datafree) // I - Free function
|
||||
{
|
||||
obj->data = data;
|
||||
obj->datafree = datafree;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'write_obj_header()' - Write the object header...
|
||||
//
|
||||
|
@ -92,6 +92,9 @@
|
||||
|
||||
# define PDFIO_MAX_DEPTH 32 // Maximum nesting depth for values
|
||||
|
||||
typedef void (*_pdfio_extfree_t)(void *);
|
||||
// Extension data free function
|
||||
|
||||
typedef enum _pdfio_mode_e // Read/write mode
|
||||
{
|
||||
_PDFIO_MODE_READ, // Read a PDF file
|
||||
@ -287,6 +290,8 @@ 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
|
||||
void *data; // Extension data, if any
|
||||
_pdfio_extfree_t datafree; // Free callback for extension data
|
||||
};
|
||||
|
||||
struct _pdfio_stream_s // Stream
|
||||
@ -365,7 +370,9 @@ 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 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;
|
||||
extern void _pdfioObjSetExtension(pdfio_obj_t *obj, void *data, _pdfio_extfree_t datafree) _PDFIO_INTERNAL;
|
||||
|
||||
extern pdfio_stream_t *_pdfioStreamCreate(pdfio_obj_t *obj, pdfio_obj_t *length_obj, pdfio_filter_t compression) _PDFIO_INTERNAL;
|
||||
extern pdfio_stream_t *_pdfioStreamOpen(pdfio_obj_t *obj, bool decode) _PDFIO_INTERNAL;
|
||||
|
@ -452,6 +452,7 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("_pdfioStreamOpen: ivlen=%d\n", (int)ivlen);
|
||||
if (ivlen > 0)
|
||||
_pdfioFileConsume(st->pdf, ivlen);
|
||||
|
||||
@ -567,6 +568,7 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
|
||||
else
|
||||
st->predictor = _PDFIO_PREDICTOR_NONE;
|
||||
|
||||
PDFIO_DEBUG("_pdfioStreamOpen: pos=%ld\n", (long)_pdfioFileTell(st->pdf));
|
||||
if (sizeof(st->cbuffer) > st->remaining)
|
||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
|
||||
else
|
||||
|
@ -383,7 +383,10 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
|
||||
return (false);
|
||||
}
|
||||
|
||||
cb = _pdfioCryptoMakeReader(pdf, obj, &ctx, v->value.binary.data, &ivlen);
|
||||
ivlen = v->value.binary.datalen;
|
||||
if ((cb = _pdfioCryptoMakeReader(pdf, obj, &ctx, v->value.binary.data, &ivlen)) == NULL)
|
||||
return (false);
|
||||
|
||||
templen = (cb)(&ctx, temp, v->value.binary.data + ivlen, v->value.binary.datalen - ivlen);
|
||||
|
||||
// Copy the decrypted string back to the value and adjust the length...
|
||||
|
4
pdfio.h
4
pdfio.h
@ -23,7 +23,7 @@ extern "C" {
|
||||
// Version number...
|
||||
//
|
||||
|
||||
# define PDFIO_VERSION "1.1.2"
|
||||
# define PDFIO_VERSION "1.2.0"
|
||||
|
||||
|
||||
//
|
||||
@ -180,10 +180,12 @@ extern bool pdfioDictSetStringf(pdfio_dict_t *dict, const char *key, const char
|
||||
extern bool pdfioFileClose(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||
extern pdfio_file_t *pdfioFileCreate(const char *filename, const char *version, pdfio_rect_t *media_box, pdfio_rect_t *crop_box, pdfio_error_cb_t error_cb, void *error_data) _PDFIO_PUBLIC;
|
||||
extern pdfio_obj_t *pdfioFileCreateArrayObj(pdfio_file_t *pdf, pdfio_array_t *array) _PDFIO_PUBLIC;
|
||||
extern pdfio_obj_t *pdfioFileCreateNumberObj(pdfio_file_t *pdf, double number) _PDFIO_PUBLIC;
|
||||
extern pdfio_obj_t *pdfioFileCreateObj(pdfio_file_t *pdf, pdfio_dict_t *dict) _PDFIO_PUBLIC;
|
||||
extern pdfio_file_t *pdfioFileCreateOutput(pdfio_output_cb_t output_cb, void *output_ctx, const char *version, pdfio_rect_t *media_box, pdfio_rect_t *crop_box, pdfio_error_cb_t error_cb, void *error_data) _PDFIO_PUBLIC;
|
||||
// TODO: Add number, array, string, etc. versions of pdfioFileCreateObject?
|
||||
extern pdfio_stream_t *pdfioFileCreatePage(pdfio_file_t *pdf, pdfio_dict_t *dict) _PDFIO_PUBLIC;
|
||||
extern pdfio_obj_t *pdfioFileCreateStringObj(pdfio_file_t *pdf, const char *s) _PDFIO_PUBLIC;
|
||||
extern pdfio_file_t *pdfioFileCreateTemporary(char *buffer, size_t bufsize, const char *version, pdfio_rect_t *media_box, pdfio_rect_t *crop_box, pdfio_error_cb_t error_cb, void *error_data) _PDFIO_PUBLIC;
|
||||
extern pdfio_obj_t *pdfioFileFindObj(pdfio_file_t *pdf, size_t number) _PDFIO_PUBLIC;
|
||||
extern const char *pdfioFileGetAuthor(pdfio_file_t *pdf) _PDFIO_PUBLIC;
|
||||
|
13
pdfio.pc.in
13
pdfio.pc.in
@ -1,6 +1,13 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: pdfio
|
||||
Description: PDF read/write library
|
||||
Version: @PDFIO_VERSION@
|
||||
URL: https://www.msweet.org/pdfio
|
||||
Requires: zlib >= 1.0
|
||||
Libs: -L${prefix}/lib -lpdfio -lm
|
||||
Cflags: -I${prefix}/include
|
||||
Requires: @PKGCONFIG_REQUIRES@
|
||||
Libs: @PKGCONFIG_LIBS@
|
||||
Libs.private: @PKGCONFIG_LIBS_PRIVATE@ -lm
|
||||
Cflags: @PKGCONFIG_CFLAGS@
|
||||
|
11
pdfio1.def
11
pdfio1.def
@ -1,5 +1,5 @@
|
||||
LIBRARY pdfio1
|
||||
VERSION 1.0
|
||||
VERSION 1.2
|
||||
EXPORTS
|
||||
_pdfioArrayDebug
|
||||
_pdfioArrayDelete
|
||||
@ -47,7 +47,9 @@ _pdfioFileSeek
|
||||
_pdfioFileTell
|
||||
_pdfioFileWrite
|
||||
_pdfioObjDelete
|
||||
_pdfioObjGetExtension
|
||||
_pdfioObjLoad
|
||||
_pdfioObjSetExtension
|
||||
_pdfioStreamCreate
|
||||
_pdfioStreamOpen
|
||||
_pdfioStringIsAllocated
|
||||
@ -136,9 +138,12 @@ pdfioContentSetTextXScaling
|
||||
pdfioContentStroke
|
||||
pdfioContentTextBegin
|
||||
pdfioContentTextEnd
|
||||
pdfioContentTextMeasure
|
||||
pdfioContentTextMoveLine
|
||||
pdfioContentTextMoveTo
|
||||
pdfioContentTextNextLine
|
||||
pdfioContentTextNewLine
|
||||
pdfioContentTextNewLineShow
|
||||
pdfioContentTextNewLineShowf
|
||||
pdfioContentTextShow
|
||||
pdfioContentTextShowJustified
|
||||
pdfioContentTextShowf
|
||||
@ -176,9 +181,11 @@ pdfioFileCreateFontObjFromFile
|
||||
pdfioFileCreateICCObjFromFile
|
||||
pdfioFileCreateImageObjFromData
|
||||
pdfioFileCreateImageObjFromFile
|
||||
pdfioFileCreateNumberObj
|
||||
pdfioFileCreateObj
|
||||
pdfioFileCreateOutput
|
||||
pdfioFileCreatePage
|
||||
pdfioFileCreateStringObj
|
||||
pdfioFileCreateTemporary
|
||||
pdfioFileFindObj
|
||||
pdfioFileGetAuthor
|
||||
|
@ -3,7 +3,7 @@
|
||||
<metadata>
|
||||
<id>pdfio_native</id>
|
||||
<title>PDFio Library for VS2019+</title>
|
||||
<version>1.1.2</version>
|
||||
<version>1.2.0</version>
|
||||
<authors>Michael R Sweet</authors>
|
||||
<owners>michaelrsweet</owners>
|
||||
<projectUrl>https://github.com/michaelrsweet/pappl</projectUrl>
|
||||
@ -16,7 +16,7 @@
|
||||
<copyright>Copyright © 2019-2023 by Michael R Sweet</copyright>
|
||||
<tags>pdf file native</tags>
|
||||
<dependencies>
|
||||
<dependency id="pdfio_native.redist" version="1.1.2" />
|
||||
<dependency id="pdfio_native.redist" version="1.2.0" />
|
||||
<dependency id="zlib_native.redist" version="1.2.11" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<metadata>
|
||||
<id>pdfio_native.redist</id>
|
||||
<title>PDFio Library for VS2019+</title>
|
||||
<version>1.1.2</version>
|
||||
<version>1.2.0</version>
|
||||
<authors>Michael R Sweet</authors>
|
||||
<owners>michaelrsweet</owners>
|
||||
<projectUrl>https://github.com/michaelrsweet/pappl</projectUrl>
|
||||
|
97
testpdfio.c
97
testpdfio.c
@ -44,7 +44,7 @@ static int verify_image(pdfio_file_t *pdf, size_t number);
|
||||
static int write_alpha_test(pdfio_file_t *pdf, int number, pdfio_obj_t *font);
|
||||
static int write_color_patch(pdfio_stream_t *st, bool device);
|
||||
static int write_color_test(pdfio_file_t *pdf, int number, pdfio_obj_t *font);
|
||||
static int write_font_test(pdfio_file_t *pdf, int number, pdfio_obj_t *font, bool unicode);
|
||||
static int write_font_test(pdfio_file_t *pdf, int number, pdfio_obj_t *font, const char *textfontfile, bool unicode);
|
||||
static int write_header_footer(pdfio_stream_t *st, const char *title, int number);
|
||||
static pdfio_obj_t *write_image_object(pdfio_file_t *pdf, _pdfio_predictor_t predictor);
|
||||
static int write_images_test(pdfio_file_t *pdf, int number, pdfio_obj_t *font);
|
||||
@ -455,7 +455,7 @@ do_test_file(const char *filename, // I - PDF filename
|
||||
}
|
||||
}
|
||||
|
||||
printf(" Page #%d is %gx%g.\n", (int)n + 1, media_box.x2, media_box.y2);
|
||||
printf(" Page #%d (obj %d) is %gx%g.\n", (int)n + 1, (int)pdfioObjGetNumber(obj), media_box.x2, media_box.y2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2229,14 +2229,20 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file
|
||||
//
|
||||
|
||||
static int // O - 1 on failure, 0 on success
|
||||
write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
int number, // I - Page number
|
||||
pdfio_obj_t *font, // I - Page number font
|
||||
bool unicode) // I - Use Unicode font?
|
||||
write_font_test(
|
||||
pdfio_file_t *pdf, // I - PDF file
|
||||
int number, // I - Page number
|
||||
pdfio_obj_t *font, // I - Page number font
|
||||
const char *textfontfile, // I - Text font file
|
||||
bool unicode) // I - Use Unicode font?
|
||||
{
|
||||
pdfio_dict_t *dict; // Page dictionary
|
||||
pdfio_stream_t *st; // Page contents stream
|
||||
pdfio_obj_t *opensans; // OpenSans-Regular font
|
||||
pdfio_obj_t *textfont; // Text font
|
||||
char title[256], // Page title
|
||||
textname[256], // Name of text font
|
||||
*ptr; // Pointer into name
|
||||
double width; // Text width
|
||||
int i; // Looping var
|
||||
static const char * const welcomes[] =// "Welcome" in many languages
|
||||
{
|
||||
@ -2387,28 +2393,16 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
"Märr-ŋamathirri",
|
||||
"Ẹ ku abọ",
|
||||
"Kíimak 'oolal",
|
||||
"Ngiyakwemukela"
|
||||
"Ngiyakwemukela",
|
||||
"いらっしゃいませ"
|
||||
};
|
||||
|
||||
|
||||
#if 0
|
||||
if (unicode)
|
||||
{
|
||||
fputs("pdfioFileCreateFontObjFromFile(NotoSansJP-Regular.otf): ", stdout);
|
||||
if ((opensans = pdfioFileCreateFontObjFromFile(pdf, "testfiles/NotoSansJP-Regular.otf", true)) != NULL)
|
||||
puts("PASS");
|
||||
else
|
||||
return (1);
|
||||
}
|
||||
printf("pdfioFileCreateFontObjFromFile(%s): ", textfontfile);
|
||||
if ((textfont = pdfioFileCreateFontObjFromFile(pdf, textfontfile, unicode)) != NULL)
|
||||
puts("PASS");
|
||||
else
|
||||
#endif // 0
|
||||
{
|
||||
fputs("pdfioFileCreateFontObjFromFile(OpenSans-Regular.ttf): ", stdout);
|
||||
if ((opensans = pdfioFileCreateFontObjFromFile(pdf, "testfiles/OpenSans-Regular.ttf", unicode)) != NULL)
|
||||
puts("PASS");
|
||||
else
|
||||
return (1);
|
||||
}
|
||||
return (1);
|
||||
|
||||
fputs("pdfioDictCreate: ", stdout);
|
||||
if ((dict = pdfioDictCreate(pdf)) != NULL)
|
||||
@ -2423,7 +2417,7 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
return (1);
|
||||
|
||||
fputs("pdfioPageDictAddFont(F2): ", stdout);
|
||||
if (pdfioPageDictAddFont(dict, "F2", opensans))
|
||||
if (pdfioPageDictAddFont(dict, "F2", textfont))
|
||||
puts("PASS");
|
||||
else
|
||||
return (1);
|
||||
@ -2435,7 +2429,21 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
else
|
||||
return (1);
|
||||
|
||||
if (write_header_footer(st, unicode ? "Unicode TrueType Font Test" : "CP1252 TrueType Font Test", number))
|
||||
if ((ptr = strrchr(textfontfile, '/')) != NULL)
|
||||
strncpy(textname, ptr + 1, sizeof(textname) - 1);
|
||||
else
|
||||
strncpy(textname, textfontfile, sizeof(textname) - 1);
|
||||
|
||||
textname[sizeof(textname) - 1] = '\0';
|
||||
if ((ptr = strrchr(textname, '.')) != NULL)
|
||||
*ptr = '\0';
|
||||
|
||||
if (unicode)
|
||||
snprintf(title, sizeof(title), "Unicode %s Font Test", textname);
|
||||
else
|
||||
snprintf(title, sizeof(title), "CP1252 %s Font Test", textname);
|
||||
|
||||
if (write_header_footer(st, title, number))
|
||||
goto error;
|
||||
|
||||
fputs("pdfioContentTextBegin(): ", stdout);
|
||||
@ -2456,8 +2464,8 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
else
|
||||
goto error;
|
||||
|
||||
fputs("pdfioContentTextMoveTo(36.0, 702.0): ", stdout);
|
||||
if (pdfioContentTextMoveTo(st, 36.0, 702.0))
|
||||
fputs("pdfioContentTextMoveTo(198.0, 702.0): ", stdout);
|
||||
if (pdfioContentTextMoveTo(st, 198.0, 702.0))
|
||||
puts("PASS");
|
||||
else
|
||||
return (1);
|
||||
@ -2466,18 +2474,36 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
{
|
||||
if (i > 0 && (i % 50) == 0)
|
||||
{
|
||||
fputs("pdfioContentTextMoveTo(200.0, 600.0): ", stdout);
|
||||
if (pdfioContentTextMoveTo(st, 200.0, 600.0))
|
||||
fputs("pdfioContentTextMoveTo(162.0, 600.0): ", stdout);
|
||||
if (pdfioContentTextMoveTo(st, 162.0, 600.0))
|
||||
puts("PASS");
|
||||
else
|
||||
return (1);
|
||||
}
|
||||
|
||||
printf("pdfioContentTextMeasure(\"%s\"): ", welcomes[i]);
|
||||
if ((width = pdfioContentTextMeasure(textfont, welcomes[i], 10.0)) >= 0.0)
|
||||
puts("PASS");
|
||||
else
|
||||
return (1);
|
||||
|
||||
printf("pdfioContextTextMoveTo(%g, 0.0): ", -width);
|
||||
if (pdfioContentTextMoveTo(st, -width, 0.0))
|
||||
puts("PASS");
|
||||
else
|
||||
return (1);
|
||||
|
||||
printf("pdfioContentTextShowf(\"%s\"): ", welcomes[i]);
|
||||
if (pdfioContentTextShowf(st, unicode, "%s\n", welcomes[i]))
|
||||
puts("PASS");
|
||||
else
|
||||
return (1);
|
||||
|
||||
printf("pdfioContextTextMoveTo(%g, 0.0): ", width);
|
||||
if (pdfioContentTextMoveTo(st, width, 0.0))
|
||||
puts("PASS");
|
||||
else
|
||||
return (1);
|
||||
}
|
||||
|
||||
fputs("pdfioContentTextEnd(): ", stdout);
|
||||
@ -3390,14 +3416,17 @@ write_unit_file(
|
||||
return (1);
|
||||
|
||||
// Test TrueType fonts...
|
||||
if (write_font_test(outpdf, 9, helvetica, false))
|
||||
if (write_font_test(outpdf, 9, helvetica, "testfiles/OpenSans-Regular.ttf", false))
|
||||
return (1);
|
||||
|
||||
if (write_font_test(outpdf, 10, helvetica, true))
|
||||
if (write_font_test(outpdf, 10, helvetica, "testfiles/OpenSans-Regular.ttf", true))
|
||||
return (1);
|
||||
|
||||
if (write_font_test(outpdf, 11, helvetica, "testfiles/NotoSansJP-Regular.otf", true))
|
||||
return (1);
|
||||
|
||||
// Print this text file...
|
||||
if (write_text_test(outpdf, 11, helvetica, "README.md"))
|
||||
if (write_text_test(outpdf, 12, helvetica, "README.md"))
|
||||
return (1);
|
||||
|
||||
fputs("pdfioFileGetNumPages: ", stdout);
|
||||
|
304
testttf.c
Normal file
304
testttf.c
Normal file
@ -0,0 +1,304 @@
|
||||
//
|
||||
// Unit test program for TTF library
|
||||
//
|
||||
// https://github.com/michaelrsweet/ttf
|
||||
//
|
||||
// Copyright © 2018-2023 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);
|
||||
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);
|
||||
}
|
52
ttf.c
52
ttf.c
@ -71,7 +71,7 @@ typedef __int64 ssize_t; // POSIX type not present on Windows...
|
||||
|
||||
|
||||
//
|
||||
// DEBUG is typically defined for debug builds. TTF_DEBUG maps to printf when
|
||||
// DEBUG is typically defined for debug builds. TTF_DEBUG maps to fprintf when
|
||||
// DEBUG is defined and is a no-op otherwise...
|
||||
//
|
||||
|
||||
@ -448,7 +448,7 @@ ttfCreate(const char *filename, // I - Filename
|
||||
font->cap_height = font->ascent;
|
||||
|
||||
if (font->x_height == 0)
|
||||
font->x_height = 3 * font->ascent / 5;
|
||||
font->x_height = 3 * font->ascent / 5;
|
||||
|
||||
// Build a sparse glyph widths table...
|
||||
font->min_char = -1;
|
||||
@ -477,6 +477,11 @@ ttfCreate(const char *filename, // I - Filename
|
||||
else
|
||||
font->widths[bin][i & 255] = widths[glyph];
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (i >= ' ' && i < 127 && font->widths[0])
|
||||
TTF_DEBUG("ttfCreate: width['%c']=%d(%d)\n", (char)i, font->widths[0][i].width, font->widths[0][i].left_bearing);
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
// Cleanup and return the font...
|
||||
@ -687,9 +692,6 @@ ttfGetExtents(
|
||||
ch = *s++;
|
||||
}
|
||||
|
||||
// Issue #1: Offset past ".notdef"...
|
||||
ch ++;
|
||||
|
||||
// Find its width...
|
||||
if ((widths = font->widths[ch / 256]) != NULL)
|
||||
{
|
||||
@ -736,17 +738,6 @@ ttfGetFamily(ttf_t *font) // I - Font
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'ttfIsFixedPitch()' - Determine whether a font is fixedpitch.
|
||||
//
|
||||
|
||||
bool // O - `true` if fixed pitch, `false` otherwise
|
||||
ttfIsFixedPitch(ttf_t *font) // I - Font
|
||||
{
|
||||
return (font ? font->is_fixed : false);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'ttfGetItalicAngle()' - Get the italic angle.
|
||||
//
|
||||
@ -855,13 +846,14 @@ int // O - Width in 1000ths
|
||||
ttfGetWidth(ttf_t *font, // I - Font
|
||||
int ch) // I - Unicode character
|
||||
{
|
||||
int bin = ch >> 8; // Bin in widths array
|
||||
int bin = ch >> 8; // Bin in widths array
|
||||
|
||||
|
||||
// Range check input...
|
||||
if (!font || ch < ' ' || ch == 0x7f)
|
||||
return (0);
|
||||
else if (font->widths[bin])
|
||||
|
||||
if (font->widths[bin])
|
||||
return ((int)(1000.0f * font->widths[bin][ch & 255].width / font->units));
|
||||
else if (font->widths[0]) // .notdef
|
||||
return ((int)(1000.0f * font->widths[0][0].width / font->units));
|
||||
@ -881,6 +873,17 @@ ttfGetXHeight(ttf_t *font) // I - Font
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'ttfIsFixedPitch()' - Determine whether a font is fixedpitch.
|
||||
//
|
||||
|
||||
bool // O - `true` if fixed pitch, `false` otherwise
|
||||
ttfIsFixedPitch(ttf_t *font) // I - Font
|
||||
{
|
||||
return (font ? font->is_fixed : false);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'copy_name()' - Copy a name string from a font.
|
||||
//
|
||||
@ -1279,7 +1282,7 @@ read_cmap(ttf_t *font) // I - Font
|
||||
|
||||
// Based on the end code of the segent table, allocate space for the
|
||||
// uncompressed cmap table...
|
||||
segCount --; // Last segment is not used (sigh)
|
||||
// segCount --; // Last segment is not used (sigh)
|
||||
|
||||
font->num_cmap = segments[segCount - 1].endCode + 1;
|
||||
font->cmap = cmapptr = (int *)malloc(font->num_cmap * sizeof(int));
|
||||
@ -1304,17 +1307,18 @@ read_cmap(ttf_t *font) // I - Font
|
||||
{
|
||||
// Use an "obscure indexing trick" (words from the spec, not
|
||||
// mine) to look up the glyph index...
|
||||
temp = segment->idRangeOffset / 2 + ch - segment->startCode + seg - segCount - 1;
|
||||
temp = segment->idRangeOffset / 2 - segCount + (ch - segment->startCode) + (segment - segments);
|
||||
|
||||
if (temp < 0 || temp >= numGlyphIdArray || !glyphIdArray[temp])
|
||||
TTF_DEBUG("read_cmap: ch=%d, temp=%d\n", ch, temp);
|
||||
if (temp < 0 || temp >= numGlyphIdArray)
|
||||
glyph = -1;
|
||||
else
|
||||
glyph = ((glyphIdArray[temp] + segment->idDelta) & 65535) - 1;
|
||||
glyph = (glyphIdArray[temp] + segment->idDelta) & 65535;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just use idDelta to compute a glyph index...
|
||||
glyph = ((ch + segment->idDelta) & 65535) - 1;
|
||||
glyph = (ch + segment->idDelta) & 65535;
|
||||
}
|
||||
|
||||
cmapptr[ch] = glyph;
|
||||
@ -1581,6 +1585,8 @@ read_hmtx(ttf_t *font, // I - Font
|
||||
{
|
||||
widths[i].width = (short)read_ushort(font);
|
||||
widths[i].left_bearing = (short)read_short(font);
|
||||
|
||||
TTF_DEBUG("read_hmtx: widths[%d].width=%d, .left_bearing=%d\n", i, widths[i].width, widths[i].left_bearing);
|
||||
}
|
||||
|
||||
return (widths);
|
||||
|
Reference in New Issue
Block a user