feat!: drop deprecated API and the pdf2htmlEX / wvWare backends - #622
Merged
Conversation
Clears the deck for the next major version.
Removed deprecated surface:
- the `WITH_PDF2HTMLEX` / `WITH_WVWARE` / `WITH_LIBMAGIC` CMake option
aliases (use the `ODR_`-prefixed ones)
- the `[[deprecated]]` `FileMeta(FileType, bool, optional<DocumentMeta>)`
constructor
Removed the external decoder engines:
- `DecoderEngine::poppler` / `DecoderEngine::wvware` — `odr` is now the only
engine
- `internal/pdf_poppler/`, `internal/oldms_wvware/`,
`internal/html/{pdf2htmlex,wvware}_wrapper.*`
- the `ODR_WITH_PDF2HTMLEX` / `ODR_WITH_WVWARE` build options and the
`with_pdf2htmlEX` / `with_wvWare` conan options, plus their transitive
dependencies in `conan.lock` (poppler, fontconfig, cairo, fontforge,
boost, …)
- the `GlobalParams` fontconfig / poppler / pdf2htmlEX data paths, with the
matching Python and Java bindings
PDF now always goes through the in-house parser, `.doc` through `oldms`.
This also drops the GPL-licensed optional dependencies, so the distributed
library is MPL-2.0 throughout.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PFa1Vk3GS58oJYWh1bcHSi
andiwand
force-pushed
the
feat/drop-deprecated-and-external-engines
branch
from
July 26, 2026 16:27
f81d6dc to
f652e18
Compare
andiwand
marked this pull request as ready for review
July 26, 2026 17:47
andiwand
added a commit
that referenced
this pull request
Jul 27, 2026
* feat!: clean up the public API for 6.0.0 Breaking changes to `odr::` ahead of the 6.0.0 tag, plus two long-standing defects in the public element API. Fixed: * `ElementIterator::operator++(int)` was `const`, so it could not advance, and returned the successor rather than the pre-increment value — `it++` silently violated the forward-iterator contract the class advertises. * `Element` and `ElementIterator` equality compared only the element identifier, so element n of one document compared equal to element n of an unrelated one. Non-existent iterators still compare equal to each other so `ElementRange::end()` keeps working. Changed: * Shape geometry is typed: `Frame`, `Rect`, `Line`, `Circle` and `CustomShape` return `Measure` instead of `std::string`, and `Frame::z_index` returns `std::optional<std::int32_t>`. The OOXML and ppt engines already built a `Measure` internally and called `to_string()` only to satisfy the string interface, so for them this is a simplification. * `Measure::to_string` renders 7 significant digits in positional notation via the new `util::number::to_string_significant`. The iostream default rounded to 4 (a drawing coordinate of `-6734.61mm` came out `-6735mm`) and could fall back to scientific notation, which CSS and SVG lengths reject. 7 digits is also the ceiling a `float` carries, so an xlsx column width stored as float `68.55` does not come back as `68.550003`. * `TextStyle::font_name` is `std::optional<std::string_view>` rather than `const char *`, matching its sibling fields and keeping the zero-copy contract the oldms style registries are built around. * Every exception derives from `odr::Exception`. Decoders still throw plain `std::runtime_error` for malformed input with no dedicated type, so that remains the widest net. Mirrored in Python as `pyodr.Error`. * `Color` uses named factories `from_rgb` / `from_argb`, replacing the `Color(std::uint32_t, bool dummy)` disambiguator. * `html::edit` takes `std::string_view`; `Html::config()` is `const`. * `Measure` moved to `<odr/quantity.hpp>`, where AGENTS.md already documented it; `<odr/style.hpp>` still provides it. Removed: * `DecoderEngine` and the whole decoder-selection dimension. Since the external backends went in #622 the enum had one value and could not select anything. Drops `DecodePreference::with_engine` / `engine_priority`, `list_decoder_engines`, `decoder_engine_by_name` / `_to_string`, `DecodedFile::decoder_engine`, both decoder-engine exceptions, the `abstract::DecodedFile` hook and its twelve engine overrides, and the bindings' equivalents including `DecoderEngine.java`. Also drops a duplicate `table_position.cpp` from `ODR_SOURCE_FILES`, documents `word_perfect` / `rich_text_format` as detection-only, corrects the README (json is supported), and adds CHANGELOG.md with an API stability policy. Reference outputs regenerated: 232 files, numeric formatting only, no structural change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: reference the PR from the 6.0.0 changelog entries Every other entry cites its PR; the ones added here had no number until the PR existed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix!: never leave a DynamicUnit null, and drop the public const char * A default-constructed `DynamicUnit` left `m_unit` null while `name()`, `to_string()` and `to_stream()` all dereferenced it unconditionally. The geometry work in this branch made that reachable: an ODF shape missing one of its `svg:*` attributes fell back to `Measure(0, DynamicUnit())`, and rendering it segfaulted instead of emitting a zero length. Reported by Codex on #627. Fixed at the invariant rather than the call sites: the default constructor now takes the registered empty unit, the same one `Measure("5")` parses out of a bare number. `m_unit` is therefore never null, and a fallback measure compares equal to the parsed equivalent instead of being a look-alike that isn't. Also replaces the remaining `const char *` in the public headers: * `DynamicUnit` and `Quantity` take `std::string_view`. `Quantity` copies into a buffer first, since `std::strtod` needs a terminator a view does not promise, and stops treating a negative `char` as UB in `std::isspace`. * `DocumentPath`'s `const char *` and `const std::string &` constructors collapse into one taking `std::string_view`. * `CfbError` takes `const std::string &`, like its forty siblings. `File::memory_data()` keeps `const char *`: it is a pointer to bytes paired with `size()`, not a string. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix!: return the file's bytes as a view, and report MemoryFile as memory `File::memory_data()` returned a bare `const char *` that only meant anything alongside `size()`, and used null to signal "not in memory". It now returns `std::optional<std::string_view>`, mirroring the `disk_path()` next to it: the path if the file is on disk, the bytes if it is in memory. The view carries its own length, so the pointer can no longer be read without one. Also fixes `MemoryFile::location()`, which reported `FileLocation::disk`. Nothing branched on it internally — it is only passed through to the bindings — so this corrects what the API reports rather than changing any behaviour. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 Generated with Claude Code
Clears the deck for the next major version.
Deprecated surface removed
WITH_PDF2HTMLEX/WITH_WVWARE/WITH_LIBMAGIC— use theODR_-prefixed options.[[deprecated]] FileMeta(FileType, bool, std::optional<DocumentMeta>).pdf2htmlEX / poppler / wvWare removed
DecoderEngine::popplerandDecoderEngine::wvware;odris now the only engine. PDF always goes through the in-house parser,.docthrougholdms.internal/pdf_poppler/,internal/oldms_wvware/,internal/html/pdf2htmlex_wrapper.*,internal/html/wvware_wrapper.*.ODR_WITH_PDF2HTMLEX/ODR_WITH_WVWAREand conan optionswith_pdf2htmlEX/with_wvWare, plus theFONTCONFIG_DATA_PATH/POPPLER_DATA_PATH/PDF2HTMLEX_DATA_PATHplumbing and the asset bundling that went with them.GlobalParams::{,set_}fontconfig_data_path/poppler_data_path/pdf2htmlex_data_path, and their Python (pyodr.GlobalParams) and Java (app.opendocument.core.GlobalParams) counterparts.project_info::has_wvware()/has_pdf2htmlex()likewise.conan.lockpruned to the resulting graph — 45 entries gone (poppler, poppler-data, pdf2htmlex, wvware, fontconfig, fontforge, cairo, boost, freetype, glib, …). Kept every surviving entry at its existing recipe revision; the diff is deletions only.build_test.yml,python.yml),pyproject.toml,README.md,AGENTS.md,docs/design/README.md,python/README.md,jni/README.mdupdated accordingly.Side effect worth calling out: pdf2htmlEX and wvWare were the GPL-licensed optional dependencies, so the distributed library is now MPL-2.0 throughout. The license note in
README.mdis gone.Verified locally (
cmake-build-relwithdebinfo)odr,odr_test,translate/meta/back_translate/server,pyodr_core,odr_jniall build clean.odr_testexcluding the HTML-output suite: 454/454 pass. Spot-checked*odr_public_odt*from the output suite: 10/10.ctest --test-dir cmake-build-relwithdebinfo/jni: 1/1 pass.pytest python/tests: 32/32 pass.Left alone deliberately
testmatrix were commented out with# fails at the moment because of pdf2htmlex. That blocker is gone, but the reference output is generated on macOS, so re-enabling them needs a cross-platform comparison run first — I updated the comment instead of flipping them on. Say the word and I'll enable them.html.hpp/html/pdf_file.cpp/pdf/READING_ORDER.mdstill name pdf2htmlEX and poppler, but only as descriptions of their technique (the single-layer text model,pdftotext's XY-cut). Those are references to external projects, not to anything we build.conan-odr-indexis a separate repo (submodule); itspdf2htmlex/wvware/popplerrecipes are untouched and would need their own PR.