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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 163 additions & 20 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,83 @@ endif ()

MESSAGE("Final os/arch: " ${OSSUFFIX}/${ARCHSUFFIX})

set(XML_LIBRARY ${LIBXML_SUBDIR}/${OSSUFFIX}/${ARCHSUFFIX}/libxml2.a)
set(PNG_LIBRARY ${PNG_SUBDIR}/${OSSUFFIX}/${ARCHSUFFIX}/libpng.a)
set(ZLIB_LIBRARY ${ZLIB_SUBDIR}/${OSSUFFIX}/${ARCHSUFFIX}/libz.a)
set(FREETYPE_LIBRARY ${FREETYPE_SUBDIR}/${OSSUFFIX}/${ARCHSUFFIX}/libfreetype.a)
set(ICUUC_LIBRARY ${ICU_SUBDIR}/${OSSUFFIX}/${ARCHSUFFIX}/libicuuc.a)
set(ICUDATA_LIBRARY ${ICU_SUBDIR}/${OSSUFFIX}/${ARCHSUFFIX}/libicudata.a)
# ── WINDOWS/MinGW SUPPORT: find system libraries via pkg-config ──────────────
#
# What this block does:
# When building on Windows with MinGW (a toolchain that lets you compile
# Linux-style C/C++ code on Windows), this block finds the required libraries
# (libxml2, libpng, zlib, freetype, ICU) using the system's installed copies
# instead of the pre-built static library files (.a files) that are bundled
# ("vendored") in the pdfalto source tree.
#
# Why MinGW needs different treatment:
# The vendored static libraries were compiled for Linux and Mac. They cannot
# be linked into a Windows executable. Additionally, the vendored ICU header
# files trigger compile errors with GCC 15+ (the version of the C++ compiler
# shipped with modern MinGW). By using the system-installed versions (from
# MSYS2's package manager), we get headers and libraries that are already
# built for Windows and compatible with the current compiler.
#
# What pkg-config is:
# pkg-config is a helper tool that answers the question "where are library X's
# header files and compiled code on this system?" When you install a library
# through a package manager (like MSYS2's pacman on Windows, or apt on Linux),
# it registers a small ".pc" file that lists the include paths, library paths,
# and linker flags. The commands below ask pkg-config for that information.
#
# What each CMake command does:
# find_package(PkgConfig REQUIRED)
# -- Tells CMake to locate the pkg-config tool itself. REQUIRED means
# "stop with an error if pkg-config is not installed."
#
# pkg_check_modules(LIBXML2 REQUIRED libxml-2.0)
# -- Asks pkg-config: "Is libxml-2.0 installed? If so, store its include
# paths in LIBXML2_INCLUDE_DIRS, its library names in LIBXML2_LIBRARIES,
# and its library folder paths in LIBXML2_LIBRARY_DIRS." REQUIRED means
# "stop with an error if the library is not found."
# -- The same pattern repeats for libpng, zlib, freetype2, and icu-uc.
#
# set(XML_LIBRARY ${LIBXML2_LIBRARIES})
# -- Stores the library name(s) that pkg-config found into the variable
# XML_LIBRARY, which the rest of this CMake file uses when linking.
#
# include_directories(...)
# -- Tells the compiler "also look in these folders for #include header
# files." Without this, the compiler would not find <libxml/parser.h>,
# <unicode/normalizer2.h>, etc.
#
# link_directories(...)
# -- Tells the linker "also look in these folders for the compiled library
# files." Without this, the linker would not find the .dll.a or .a files
# that contain the actual compiled code.
#
# The "else" branch (non-MinGW):
# On Linux and Mac, the vendored static .a files in the source tree are used
# directly — no pkg-config needed. These are pre-built for each platform.
# ─────────────────────────────────────────────────────────────────────────────
if (MINGW)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBXML2 REQUIRED libxml-2.0)
pkg_check_modules(LIBPNG REQUIRED libpng)
pkg_check_modules(ZLIB REQUIRED zlib)
pkg_check_modules(FREETYPE2 REQUIRED freetype2)
pkg_check_modules(ICU REQUIRED icu-uc)
set(XML_LIBRARY ${LIBXML2_LIBRARIES})
set(PNG_LIBRARY ${LIBPNG_LIBRARIES})
set(ZLIB_LIBRARY ${ZLIB_LIBRARIES})
set(FREETYPE_LIBRARY ${FREETYPE2_LIBRARIES})
set(ICUUC_LIBRARY ${ICU_LIBRARIES})
set(ICUDATA_LIBRARY "")
include_directories(${LIBXML2_INCLUDE_DIRS} ${ICU_INCLUDE_DIRS} ${FREETYPE2_INCLUDE_DIRS})
link_directories(${LIBXML2_LIBRARY_DIRS} ${ICU_LIBRARY_DIRS} ${FREETYPE2_LIBRARY_DIRS})
else ()
set(XML_LIBRARY ${LIBXML_SUBDIR}/${OSSUFFIX}/${ARCHSUFFIX}/libxml2.a)
set(PNG_LIBRARY ${PNG_SUBDIR}/${OSSUFFIX}/${ARCHSUFFIX}/libpng.a)
set(ZLIB_LIBRARY ${ZLIB_SUBDIR}/${OSSUFFIX}/${ARCHSUFFIX}/libz.a)
set(FREETYPE_LIBRARY ${FREETYPE_SUBDIR}/${OSSUFFIX}/${ARCHSUFFIX}/libfreetype.a)
set(ICUUC_LIBRARY ${ICU_SUBDIR}/${OSSUFFIX}/${ARCHSUFFIX}/libicuuc.a)
set(ICUDATA_LIBRARY ${ICU_SUBDIR}/${OSSUFFIX}/${ARCHSUFFIX}/libicudata.a)
endif ()


set(XPDF_BUILD_DIR ${XPDF_SUBDIR}/build)
Expand Down Expand Up @@ -149,23 +220,95 @@ if (HAVE_PAPER_H)
target_link_libraries(pdfalto ${PNG_LIBRARY} ${ZLIB_LIBRARY} ${XML_LIBRARY} splash xpdf goo fofi ${ICUUC_LIBRARY} ${ICUDATA_LIBRARY} ${FREETYPE_LIBRARY} dl ${PAPER_LIBRARY} pthread)
endif ()
else ()
if (HAVE_FONTCONFIG)
if (MINGW)
# ── WINDOWS/MinGW SUPPORT: Windows-specific link libraries ───────────
#
# What target_link_libraries does:
# It tells the linker (the tool that combines compiled code into a
# final executable) which libraries the program depends on. Each name
# listed here is a library whose compiled code will be merged into
# (or referenced by) the pdfalto.exe output.
#
# Why MinGW uses different system libraries than Linux:
# On Linux, programs use "dl" (dynamic loader — for loading shared
# libraries at runtime) and "pthread" (POSIX threads — for running
# code in parallel). These are Unix concepts that do not exist on
# Windows. Instead, Windows has its own system libraries:
#
# ole32 -- Provides COM (Component Object Model), which is Windows'
# system for letting programs share code and data. Some
# Windows APIs that libxml2 uses internally require COM.
#
# uuid -- Provides functions for working with UUIDs (Universally
# Unique Identifiers) — 128-bit labels used throughout
# Windows to identify COM objects, file types, etc.
#
# ws2_32 -- The Windows Sockets 2 library, which provides network
# communication (TCP/IP). libxml2 can fetch XML schemas
# over the network, so it needs socket support even though
# pdfalto itself does not use networking.
#
# Note: "dl" and "pthread" are deliberately absent here — linking them
# on Windows would cause errors because they do not exist.
# ─────────────────────────────────────────────────────────────────────
target_link_libraries(pdfalto ${PNG_LIBRARY} ${ZLIB_LIBRARY} ${XML_LIBRARY} splash xpdf goo fofi ${ICUUC_LIBRARY} ${ICUDATA_LIBRARY} ${FREETYPE_LIBRARY} ole32 uuid ws2_32)
elseif (HAVE_FONTCONFIG)
target_link_libraries(pdfalto ${PNG_LIBRARY} ${ZLIB_LIBRARY} ${XML_LIBRARY} splash xpdf goo fofi ${ICUUC_LIBRARY} ${ICUDATA_LIBRARY} ${FREETYPE_LIBRARY} dl ${FONTCONFIG_LIBRARY} pthread)
else ()
target_link_libraries(pdfalto ${PNG_LIBRARY} ${ZLIB_LIBRARY} ${XML_LIBRARY} splash xpdf goo fofi ${ICUUC_LIBRARY} ${ICUDATA_LIBRARY} ${FREETYPE_LIBRARY} dl pthread)
endif ()
endif ()

target_include_directories(
pdfalto
PUBLIC ${LIBXML_SUBDIR}/include
PUBLIC ${FREETYPE_INCLUDE_DIR}
PUBLIC ${PNG_INCLUDE_DIRS}
PUBLIC ${ZLIB_INCLUDE_DIRS}
PUBLIC ${XPDF_SUBDIR}
PUBLIC ${XPDF_SUBDIR}/goo
PUBLIC ${XPDF_SUBDIR}/fofi
PUBLIC ${XPDF_SUBDIR}/xpdf
PUBLIC ${XPDF_BUILD_DIR}
PUBLIC ${ICU_SUBDIR}/include
)
# ── WINDOWS/MinGW SUPPORT: reduced include directories ───────────────────────
#
# What target_include_directories does:
# It tells the compiler "when the source code says #include <SomeFile.h>,
# also search in these folders to find that file." Without this, the compiler
# only searches its default system folders.
#
# Why MinGW has a shorter list:
# On Linux/Mac (the "else" branch below), the compiler needs to be pointed at
# ALL vendored library headers — libxml2, freetype, png, zlib, ICU — because
# those headers are bundled in the source tree and are not installed on the
# system.
#
# On MinGW/Windows, those same libraries were installed via MSYS2's package
# manager, and their headers are already in the system include path (added
# earlier by the "include_directories" call in the pkg-config block above).
# Pointing the compiler at the vendored copies as well would create
# confusion: the compiler might pick the wrong version of a header, or —
# worse — mix vendored headers with system-installed compiled code, causing
# subtle build failures.
#
# The xpdf headers (xpdf, goo, fofi) ARE still listed here because xpdf is
# always built from the vendored source tree on every platform — it is not
# available as a system package. The XPDF_BUILD_DIR entry points to the
# generated file aconf.h (created by CMake during the xpdf build step), which
# contains platform-specific configuration settings.
# ─────────────────────────────────────────────────────────────────────────────
if (MINGW)
# MinGW: system headers via pkg-config (already added via include_directories above)
# Only add xpdf paths (vendored, no conflict) + generated aconf.h
target_include_directories(
pdfalto
PUBLIC ${XPDF_SUBDIR}
PUBLIC ${XPDF_SUBDIR}/goo
PUBLIC ${XPDF_SUBDIR}/fofi
PUBLIC ${XPDF_SUBDIR}/xpdf
PUBLIC ${XPDF_BUILD_DIR}
)
else ()
target_include_directories(
pdfalto
PUBLIC ${LIBXML_SUBDIR}/include
PUBLIC ${FREETYPE_INCLUDE_DIR}
PUBLIC ${PNG_INCLUDE_DIRS}
PUBLIC ${ZLIB_INCLUDE_DIRS}
PUBLIC ${XPDF_SUBDIR}
PUBLIC ${XPDF_SUBDIR}/goo
PUBLIC ${XPDF_SUBDIR}/fofi
PUBLIC ${XPDF_SUBDIR}/xpdf
PUBLIC ${XPDF_BUILD_DIR}
PUBLIC ${ICU_SUBDIR}/include
)
endif ()
45 changes: 44 additions & 1 deletion src/XmlAltoOutputDev.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,50 @@

#include <iostream>

using namespace std;
// ── WINDOWS SUPPORT: explicit "using" declarations instead of ──────────────
// "using namespace std;"
//
// What "using namespace std;" normally does:
// The C++ standard library puts all its names (string, vector, cout, etc.)
// inside a container called "std" (short for "standard"). Normally you must
// write "std::string" or "std::vector" every time. The shortcut
// "using namespace std;" dumps ALL of those names into the global scope so
// you can write just "string" or "vector" without the "std::" prefix.
//
// Why that shortcut causes a crash on Windows with modern compilers:
// Starting with C++17 (a version of the C++ language standard), the standard
// library added a new type called "std::byte" — a type for raw byte values.
// Separately, the Windows SDK (Microsoft's set of header files for Windows
// programming) defines its own type also called "byte" (in the file
// rpcndr.h, which gets pulled in indirectly when you include libxml2's
// headers, because libxml2 on Windows includes windows.h -> objbase.h ->
// rpcndr.h).
//
// When you write "using namespace std;", the compiler sees TWO different
// things both called "byte" — the C++ standard library's "std::byte" AND
// the Windows SDK's "byte". It cannot tell which one you mean, so it
// refuses to compile and prints an ambiguity error.
//
// This is a known issue with GCC 15+ and MinGW (the toolchain used to build
// this project on Windows). It also affects MSVC (Microsoft's compiler) in
// C++17 mode.
//
// The fix:
// Instead of importing EVERYTHING from "std" (which drags in std::byte),
// we import only the specific names this file actually uses. That way
// std::byte is never brought into the global scope, and the Windows SDK's
// "byte" is the only "byte" visible — no conflict.
//
// Each "using std::X;" line below makes one specific name available without
// the "std::" prefix. For example, "using std::string;" lets us write
// "string" instead of "std::string" throughout the file.
// ───────────────────────────────────────────────────────────────────────────
using std::string; using std::vector; using std::list; using std::set;
using std::stack; using std::cout; using std::endl;
using std::sort; using std::min; using std::max; using std::abs;
using std::min_element; using std::max_element;
using std::find; using std::distance; using std::reverse; using std::swap;
using std::to_string;

#include "ConstantsUtils.h"

Expand Down