Skip to content

feat!: drop deprecated API and the pdf2htmlEX / wvWare backends - #622

Merged
andiwand merged 1 commit into
mainfrom
feat/drop-deprecated-and-external-engines
Jul 26, 2026
Merged

feat!: drop deprecated API and the pdf2htmlEX / wvWare backends#622
andiwand merged 1 commit into
mainfrom
feat/drop-deprecated-and-external-engines

Conversation

@andiwand

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

Clears the deck for the next major version.

Deprecated surface removed

  • CMake option aliases WITH_PDF2HTMLEX / WITH_WVWARE / WITH_LIBMAGIC — use the ODR_-prefixed options.
  • [[deprecated]] FileMeta(FileType, bool, std::optional<DocumentMeta>).

pdf2htmlEX / poppler / wvWare removed

  • DecoderEngine::poppler and DecoderEngine::wvware; odr is now the only engine. PDF always goes through the in-house parser, .doc through oldms.
  • Deleted internal/pdf_poppler/, internal/oldms_wvware/, internal/html/pdf2htmlex_wrapper.*, internal/html/wvware_wrapper.*.
  • Build options ODR_WITH_PDF2HTMLEX / ODR_WITH_WVWARE and conan options with_pdf2htmlEX / with_wvWare, plus the FONTCONFIG_DATA_PATH / POPPLER_DATA_PATH / PDF2HTMLEX_DATA_PATH plumbing 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.lock pruned 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.
  • CI (build_test.yml, python.yml), pyproject.toml, README.md, AGENTS.md, docs/design/README.md, python/README.md, jni/README.md updated 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.md is gone.

Verified locally (cmake-build-relwithdebinfo)

  • odr, odr_test, translate/meta/back_translate/server, pyodr_core, odr_jni all build clean.
  • odr_test excluding 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

  • The Ubuntu jobs in the test matrix 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.
  • Comments in html.hpp / html/pdf_file.cpp / pdf/READING_ORDER.md still 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-index is a separate repo (submodule); its pdf2htmlex / wvware / poppler recipes are untouched and would need their own PR.

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
andiwand force-pushed the feat/drop-deprecated-and-external-engines branch from f81d6dc to f652e18 Compare July 26, 2026 16:27
@andiwand
andiwand marked this pull request as ready for review July 26, 2026 17:47
@andiwand
andiwand merged commit 3cc6485 into main Jul 26, 2026
18 checks passed
@andiwand
andiwand deleted the feat/drop-deprecated-and-external-engines branch July 26, 2026 17:51
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant