Skip to content

fix: Add special handling for apostrophe hyphenation#1318

Merged
znelson merged 6 commits into
crosspoint-reader:masterfrom
jpirnay:fix-hyphen_apostrophe
Mar 11, 2026
Merged

fix: Add special handling for apostrophe hyphenation#1318
znelson merged 6 commits into
crosspoint-reader:masterfrom
jpirnay:fix-hyphen_apostrophe

Conversation

@jpirnay
Copy link
Copy Markdown
Contributor

@jpirnay jpirnay commented Mar 5, 2026

Summary

Additional Context


AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing, please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? PARTIALLY (as the user provided a thorough analysis that I followed)

@jpirnay jpirnay marked this pull request as ready for review March 5, 2026 19:02
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 5, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds an apostrophe-detection helper and makes hyphenation segment-aware: treats explicit hyphens and apostrophes as separators, applies Liang patterns per alphabetic segment, computes apostrophe-contraction breaks, then sorts and deduplicates break candidates before returning offsets.

Changes

Cohort / File(s) Summary
Apostrophe helper
lib/Epub/Epub/hyphenation/HyphenationCommon.h, lib/Epub/Epub/hyphenation/HyphenationCommon.cpp
Declared and implemented bool isApostrophe(uint32_t cp) recognizing ASCII apostrophe and U+2018/U+2019 Unicode single quotes.
Segment-aware hyphenation logic
lib/Epub/Epub/hyphenation/Hyphenator.cpp
Added segment-separator detection (hyphen/apostrophe), per-segment Liang pattern application, apostrophe-contraction break rules, helpers sortAndDedupeBreakInfos, and integrated these into Hyphenator::breakOffsets (replacing prior explicit-break merge).
Docs/comments / API notes
lib/Epub/Epub/hyphenation/Hyphenator.h
Updated break-source descriptions and wording to reference separators (apostrophes/hyphens), described apostrophe-contraction handling, and reordered priority of break sources in comments.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Caller as Caller
participant Hyphenator as Hyphenator
participant Segmenter as Segmenter
participant PatternEngine as PatternEngine
participant Merger as Merger
Caller->>Hyphenator: request breakOffsets(word, lang)
Hyphenator->>Segmenter: split into alphabetic segments (sep: hyphen/apostrophe)
Segmenter-->>Hyphenator: segments + separator metadata
Hyphenator->>PatternEngine: apply Liang patterns per segment
PatternEngine-->>Hyphenator: per-segment breaks
Hyphenator->>Hyphenator: compute apostrophe contraction breaks
Hyphenator->>Merger: collect explicit, segment, contraction breaks
Merger-->>Hyphenator: sorted, deduped breakInfos
Hyphenator-->>Caller: final break offsets

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Suggested reviewers

  • lukestein
  • osteotek
  • daveallie
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title 'fix: Add special handling for apostrophe hyphenation' directly relates to the main change: introducing apostrophe-aware hyphenation logic in the hyphenation module.
Description check ✅ Passed The pull request description clearly relates to the changeset, referencing the goal of fixing/extending hyphenation logic to handle apostrophes as mentioned in issue #1186.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
lib/Epub/Epub/hyphenation/Hyphenator.cpp (1)

124-137: Consider deduplicating by byteOffset only, keeping the first entry.

The current deduplication compares both byteOffset and requiresInsertedHyphen. If two breaks exist at the same offset with different flags (one from an explicit separator, one from a pattern), both will be retained.

Since the sort places requiresInsertedHyphen=false first (which is the preferred behavior—reusing an existing separator over inserting a hyphen), deduplicating by offset alone would naturally keep the correct entry.

Suggested simplification
  infos.erase(std::unique(infos.begin(), infos.end(),
                          [](const Hyphenator::BreakInfo& a, const Hyphenator::BreakInfo& b) {
-                           return a.byteOffset == b.byteOffset && a.requiresInsertedHyphen == b.requiresInsertedHyphen;
+                           return a.byteOffset == b.byteOffset;
                          }),
              infos.end());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/Epub/Epub/hyphenation/Hyphenator.cpp` around lines 124 - 137, The dedup
logic in sortAndDedupeBreakInfos keeps entries that differ only by
requiresInsertedHyphen; change the std::unique predicate to compare only
Hyphenator::BreakInfo::byteOffset so duplicate offsets are removed (the existing
sort already orders requiresInsertedHyphen=false first, so the preferred entry
is kept); update the lambda passed to std::unique in sortAndDedupeBreakInfos to
return a.byteOffset == b.byteOffset.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lib/Epub/Epub/hyphenation/Hyphenator.cpp`:
- Around line 124-137: The dedup logic in sortAndDedupeBreakInfos keeps entries
that differ only by requiresInsertedHyphen; change the std::unique predicate to
compare only Hyphenator::BreakInfo::byteOffset so duplicate offsets are removed
(the existing sort already orders requiresInsertedHyphen=false first, so the
preferred entry is kept); update the lambda passed to std::unique in
sortAndDedupeBreakInfos to return a.byteOffset == b.byteOffset.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: eb38ac63-83c4-47f3-97d8-dfb192641b81

📥 Commits

Reviewing files that changed from the base of the PR and between 047b002 and 2615257.

📒 Files selected for processing (4)
  • lib/Epub/Epub/hyphenation/HyphenationCommon.cpp
  • lib/Epub/Epub/hyphenation/HyphenationCommon.h
  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
  • lib/Epub/Epub/hyphenation/Hyphenator.h
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: cppcheck
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2026-02-19T12:17:05.421Z
Learnt from: Uri-Tauber
Repo: crosspoint-reader/crosspoint-reader PR: 988
File: lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp:649-661
Timestamp: 2026-02-19T12:17:05.421Z
Learning: In ChapterHtmlSlimParser.cpp, when computing footnote word indices in endElement() for footnote links, the wordIndex must be cumulative across the 750-word mid-paragraph flush boundary. The correct calculation is: `wordIndex = wordsExtractedInBlock + currentTextBlock->size()`, not just `currentTextBlock->size()`. This ensures footnotes attach to the page containing their actual anchor word, even after layoutAndExtractLines(false) has extracted and removed earlier words from the block.

Applied to files:

  • lib/Epub/Epub/hyphenation/Hyphenator.h
  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
📚 Learning: 2026-02-27T22:49:59.600Z
Learnt from: ngxson
Repo: crosspoint-reader/crosspoint-reader PR: 1218
File: src/activities/ActivityManager.cpp:254-265
Timestamp: 2026-02-27T22:49:59.600Z
Learning: In this codebase, assertions are always enabled (no NDEBUG). Use assert() to crash on programmer errors and surface logic bugs during development and in production builds. Do not rely on asserts for runtime error handling; they should enforce invariants that must always hold. Keep asserts side-effect free and inexpensive, and avoid relying on them for user-visible failures. Include <cassert> where appropriate and document the invariant being tested.

Applied to files:

  • lib/Epub/Epub/hyphenation/HyphenationCommon.cpp
  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
📚 Learning: 2026-03-02T10:14:16.036Z
Learnt from: Uri-Tauber
Repo: crosspoint-reader/crosspoint-reader PR: 1245
File: lib/Epub/Epub/Section.cpp:277-308
Timestamp: 2026-03-02T10:14:16.036Z
Learning: Guideline: Strengthen serialization::readString to defend against unbounded growth when reading from disk data. Implement and enforce a maximum allowed length (e.g., a configured or reasonable constant) and validate the incoming length before resizing or allocating. Audit all call sites (e.g., BookMetadataCache, TextBlock, KOReaderCredentialStore, Section cache readers) to ensure they do not rely on unbounded len-based resizing. If the readString API must remain, add internal safeguards (bounds checks, length validation, and error handling) so per-call-site validations are not required. Ensure Section cache files remain versioned (SECTION_FILE_VERSION) and parameter mismatches invalidate caches, but do not rely on unsafe allocations; prefer safe, bounded reads with explicit errors on invalid data.

Applied to files:

  • lib/Epub/Epub/hyphenation/HyphenationCommon.cpp
  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
🔇 Additional comments (8)
lib/Epub/Epub/hyphenation/HyphenationCommon.h (1)

22-22: LGTM!

The declaration is well-placed among the other character classification functions and follows the existing signature pattern.

lib/Epub/Epub/hyphenation/HyphenationCommon.cpp (1)

110-119: LGTM!

The implementation correctly identifies the common apostrophe variants. Including 0x2018 (left single quote) alongside 0x2019 (right single quote/typographic apostrophe) provides robustness for edge cases where text might use unconventional characters.

lib/Epub/Epub/hyphenation/Hyphenator.h (1)

14-32: LGTM!

The documentation updates clearly explain the new apostrophe handling behavior, including the 3-letter minimum prefix rule to avoid stranding short clitics. The break source priority order is well-documented.

lib/Epub/Epub/hyphenation/Hyphenator.cpp (5)

62-62: LGTM!

Clean helper that correctly combines explicit hyphen and apostrophe checks for segment boundary detection.


64-97: LGTM!

The segment-based pattern breaking logic is well-structured. The index translation from segment-local to whole-word offsets (line 88) is correct, and empty segments are properly skipped via the i > segStart check.


99-122: LGTM!

The contraction break logic correctly implements the 3-letter minimum prefix rule to avoid stranding short clitics like "l'" or "d'". The segment tracking properly resets on any separator.


168-173: LGTM!

Clean refactoring to use the new helper functions. Correctly passes includeFallback=false since explicit hyphens provide reliable break points.


176-195: LGTM!

The apostrophe handling logic correctly:

  1. Detects apostrophe presence before attempting segmented breaking
  2. Runs both segment pattern breaks and contraction breaks
  3. Falls through to whole-word pattern matching if segmented approach yields no breaks (e.g., for very short segments like "l'acqua")

Comment thread lib/Epub/Epub/hyphenation/Hyphenator.cpp Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
lib/Epub/Epub/hyphenation/Hyphenator.cpp (1)

196-203: ⚠️ Potential issue | 🟠 Major

Return apostrophe-segment results even when empty to prevent fallback apostrophe splits.

At Line 200, an empty segmentedBreaks falls through to generic fallback generation later, which can still create apostrophe-adjacent breaks in fallback mode (the exact case this change is guarding against).

💡 Proposed fix
   if (hyphenator && hasApostropheLikeSeparator) {
     std::vector<BreakInfo> segmentedBreaks;
     appendSegmentPatternBreaks(cps, *hyphenator, includeFallback, segmentedBreaks);
     appendApostropheContractionBreaks(cps, segmentedBreaks);
     if (!segmentedBreaks.empty()) {
       sortAndDedupeBreakInfos(segmentedBreaks);
-      return segmentedBreaks;
     }
+    return segmentedBreaks;  // even if empty: avoid generic fallback across apostrophes
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/Epub/Epub/hyphenation/Hyphenator.cpp` around lines 196 - 203, When
hyphenator is present and hasApostropheLikeSeparator is true, always return the
segmentedBreaks vector (even if empty) after calling appendSegmentPatternBreaks
and appendApostropheContractionBreaks to avoid falling back to generic fallback
generation that can produce apostrophe-adjacent breaks; in practice, modify the
block that currently checks if (!segmentedBreaks.empty()) to unconditionally
call sortAndDedupeBreakInfos(segmentedBreaks) and return segmentedBreaks
(references: hyphenator, hasApostropheLikeSeparator, segmentedBreaks,
appendSegmentPatternBreaks, appendApostropheContractionBreaks,
sortAndDedupeBreakInfos).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@lib/Epub/Epub/hyphenation/Hyphenator.cpp`:
- Around line 196-203: When hyphenator is present and hasApostropheLikeSeparator
is true, always return the segmentedBreaks vector (even if empty) after calling
appendSegmentPatternBreaks and appendApostropheContractionBreaks to avoid
falling back to generic fallback generation that can produce apostrophe-adjacent
breaks; in practice, modify the block that currently checks if
(!segmentedBreaks.empty()) to unconditionally call
sortAndDedupeBreakInfos(segmentedBreaks) and return segmentedBreaks (references:
hyphenator, hasApostropheLikeSeparator, segmentedBreaks,
appendSegmentPatternBreaks, appendApostropheContractionBreaks,
sortAndDedupeBreakInfos).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1234a6df-e07f-44b9-9628-ec74b90903a5

📥 Commits

Reviewing files that changed from the base of the PR and between 2615257 and 1ae4f06.

📒 Files selected for processing (2)
  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
  • lib/Epub/Epub/hyphenation/Hyphenator.h
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/Epub/Epub/hyphenation/Hyphenator.h
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: cppcheck
  • GitHub Check: build
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2026-02-19T12:17:05.421Z
Learnt from: Uri-Tauber
Repo: crosspoint-reader/crosspoint-reader PR: 988
File: lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp:649-661
Timestamp: 2026-02-19T12:17:05.421Z
Learning: In ChapterHtmlSlimParser.cpp, when computing footnote word indices in endElement() for footnote links, the wordIndex must be cumulative across the 750-word mid-paragraph flush boundary. The correct calculation is: `wordIndex = wordsExtractedInBlock + currentTextBlock->size()`, not just `currentTextBlock->size()`. This ensures footnotes attach to the page containing their actual anchor word, even after layoutAndExtractLines(false) has extracted and removed earlier words from the block.

Applied to files:

  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
📚 Learning: 2026-02-27T22:49:59.600Z
Learnt from: ngxson
Repo: crosspoint-reader/crosspoint-reader PR: 1218
File: src/activities/ActivityManager.cpp:254-265
Timestamp: 2026-02-27T22:49:59.600Z
Learning: In this codebase, assertions are always enabled (no NDEBUG). Use assert() to crash on programmer errors and surface logic bugs during development and in production builds. Do not rely on asserts for runtime error handling; they should enforce invariants that must always hold. Keep asserts side-effect free and inexpensive, and avoid relying on them for user-visible failures. Include <cassert> where appropriate and document the invariant being tested.

Applied to files:

  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
📚 Learning: 2026-03-02T10:14:16.036Z
Learnt from: Uri-Tauber
Repo: crosspoint-reader/crosspoint-reader PR: 1245
File: lib/Epub/Epub/Section.cpp:277-308
Timestamp: 2026-03-02T10:14:16.036Z
Learning: Guideline: Strengthen serialization::readString to defend against unbounded growth when reading from disk data. Implement and enforce a maximum allowed length (e.g., a configured or reasonable constant) and validate the incoming length before resizing or allocating. Audit all call sites (e.g., BookMetadataCache, TextBlock, KOReaderCredentialStore, Section cache readers) to ensure they do not rely on unbounded len-based resizing. If the readString API must remain, add internal safeguards (bounds checks, length validation, and error handling) so per-call-site validations are not required. Ensure Section cache files remain versioned (SECTION_FILE_VERSION) and parameter mismatches invalidate caches, but do not rely on unsafe allocations; prefer safe, bounded reads with explicit errors on invalid data.

Applied to files:

  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
🔇 Additional comments (1)
lib/Epub/Epub/hyphenation/Hyphenator.cpp (1)

133-146: Good extraction of break sorting/deduping into a shared helper.

Centralizing this behavior reduces merge-path drift and keeps ordering semantics consistent.

@znelson znelson changed the title fix: Add special handling for apostrophe handling fix: Add special handling for apostrophe hyphenation Mar 5, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/Epub/Epub/hyphenation/Hyphenator.cpp`:
- Around line 64-97: The function appendSegmentPatternBreaks trusts
LanguageHyphenator::breakIndexes to return interior positions but may receive 0
or segment.size(), producing invalid boundary breaks; update the loop over
segIndexes in appendSegmentPatternBreaks to assert each idx is strictly interior
(use assert(idx > 0 && idx < segment.size())) and skip any index that violates
that invariant before computing cpIdx/outBreaks, while preserving the existing
cpIdx < cps.size() guard; also ensure the fallback generation
(minPrefix/minSuffix loop) cannot produce 0 or segment.size() by keeping its
bounds but the assert will catch any programmer errors from breakIndexes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 577c8383-91de-43af-840d-d5a5a5ed764f

📥 Commits

Reviewing files that changed from the base of the PR and between 1ae4f06 and c0563cf.

📒 Files selected for processing (1)
  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: cppcheck
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2026-02-27T22:49:59.600Z
Learnt from: ngxson
Repo: crosspoint-reader/crosspoint-reader PR: 1218
File: src/activities/ActivityManager.cpp:254-265
Timestamp: 2026-02-27T22:49:59.600Z
Learning: In this codebase, assertions are always enabled (no NDEBUG). Use assert() to crash on programmer errors and surface logic bugs during development and in production builds. Do not rely on asserts for runtime error handling; they should enforce invariants that must always hold. Keep asserts side-effect free and inexpensive, and avoid relying on them for user-visible failures. Include <cassert> where appropriate and document the invariant being tested.

Applied to files:

  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
📚 Learning: 2026-03-02T10:14:16.036Z
Learnt from: Uri-Tauber
Repo: crosspoint-reader/crosspoint-reader PR: 1245
File: lib/Epub/Epub/Section.cpp:277-308
Timestamp: 2026-03-02T10:14:16.036Z
Learning: Guideline: Strengthen serialization::readString to defend against unbounded growth when reading from disk data. Implement and enforce a maximum allowed length (e.g., a configured or reasonable constant) and validate the incoming length before resizing or allocating. Audit all call sites (e.g., BookMetadataCache, TextBlock, KOReaderCredentialStore, Section cache readers) to ensure they do not rely on unbounded len-based resizing. If the readString API must remain, add internal safeguards (bounds checks, length validation, and error handling) so per-call-site validations are not required. Ensure Section cache files remain versioned (SECTION_FILE_VERSION) and parameter mismatches invalidate caches, but do not rely on unsafe allocations; prefer safe, bounded reads with explicit errors on invalid data.

Applied to files:

  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
🔇 Additional comments (5)
lib/Epub/Epub/hyphenation/Hyphenator.cpp (5)

62-63: Good separator abstraction.

This helper cleanly centralizes segment-boundary semantics for explicit hyphens and apostrophes.


99-131: Contraction break guardrails look solid.

The prefix/suffix length checks at Line 124 correctly prevent short-tail splits (e.g., avoiding can'|t-style breaks).


133-146: Deterministic sort-and-dedupe is well-scoped.

Centralizing this logic improves merge consistency for break candidates from multiple sources.


178-181: Nice reuse of the shared merge path.

Using sortAndDedupeBreakInfos here avoids drift with other break-source merges.


185-203: Apostrophe-specific path is well integrated.

Segmented pattern breaks plus contraction-aware breaks are combined cleanly before returning.

Comment thread lib/Epub/Epub/hyphenation/Hyphenator.cpp
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/Epub/Epub/hyphenation/Hyphenator.cpp (1)

165-205: ⚠️ Potential issue | 🟠 Major

Don't skip apostrophe handling outside the hyphenator-only branch.

Apostrophe-specific breaks only run in the later if (hyphenator && hasApostropheLikeSeparator) block, while the explicit-hyphen path returns earlier. That leaves two holes in the new behavior: words containing both - and ' never get the apostrophe contraction break, and unsupported/no-language cases still fall back over the whole token instead of apostrophe-separated segments. Please move the apostrophe handling out of the hyphenator gate and merge appendApostropheContractionBreaks() into the explicit-hyphen path before returning.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/Epub/Epub/hyphenation/Hyphenator.cpp` around lines 165 - 205, The code
returns early from the explicit-hyphen branch without applying
apostrophe-specific contraction breaks, so words with both '-' and '\'' or cases
without a hyphenator miss apostrophe handling; detect apostrophe-like separators
(use the existing isApostrophe loop / hasApostropheLikeSeparator) before
returning from the explicit-hyphen path and call
appendApostropheContractionBreaks(cps, explicitBreakInfos) (after
appendSegmentPatternBreaks when hyphenator is present, and before
sortAndDedupeBreakInfos) so explicitBreakInfos include apostrophe contractions;
similarly, remove the dependence on hyphenator for the apostrophe-only branch by
reusing appendApostropheContractionBreaks on the segmentedBreaks path as needed
(keep calls to appendSegmentPatternBreaks, sortAndDedupeBreakInfos, and preserve
includeFallback usage).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@lib/Epub/Epub/hyphenation/Hyphenator.cpp`:
- Around line 165-205: The code returns early from the explicit-hyphen branch
without applying apostrophe-specific contraction breaks, so words with both '-'
and '\'' or cases without a hyphenator miss apostrophe handling; detect
apostrophe-like separators (use the existing isApostrophe loop /
hasApostropheLikeSeparator) before returning from the explicit-hyphen path and
call appendApostropheContractionBreaks(cps, explicitBreakInfos) (after
appendSegmentPatternBreaks when hyphenator is present, and before
sortAndDedupeBreakInfos) so explicitBreakInfos include apostrophe contractions;
similarly, remove the dependence on hyphenator for the apostrophe-only branch by
reusing appendApostropheContractionBreaks on the segmentedBreaks path as needed
(keep calls to appendSegmentPatternBreaks, sortAndDedupeBreakInfos, and preserve
includeFallback usage).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 130ccbe4-f853-489a-8b06-6b9435617927

📥 Commits

Reviewing files that changed from the base of the PR and between c0563cf and 2e739a6.

📒 Files selected for processing (1)
  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: cppcheck
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2026-02-19T12:17:05.421Z
Learnt from: Uri-Tauber
Repo: crosspoint-reader/crosspoint-reader PR: 988
File: lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp:649-661
Timestamp: 2026-02-19T12:17:05.421Z
Learning: In ChapterHtmlSlimParser.cpp, when computing footnote word indices in endElement() for footnote links, the wordIndex must be cumulative across the 750-word mid-paragraph flush boundary. The correct calculation is: `wordIndex = wordsExtractedInBlock + currentTextBlock->size()`, not just `currentTextBlock->size()`. This ensures footnotes attach to the page containing their actual anchor word, even after layoutAndExtractLines(false) has extracted and removed earlier words from the block.

Applied to files:

  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
📚 Learning: 2026-02-27T22:49:59.600Z
Learnt from: ngxson
Repo: crosspoint-reader/crosspoint-reader PR: 1218
File: src/activities/ActivityManager.cpp:254-265
Timestamp: 2026-02-27T22:49:59.600Z
Learning: In this codebase, assertions are always enabled (no NDEBUG). Use assert() to crash on programmer errors and surface logic bugs during development and in production builds. Do not rely on asserts for runtime error handling; they should enforce invariants that must always hold. Keep asserts side-effect free and inexpensive, and avoid relying on them for user-visible failures. Include <cassert> where appropriate and document the invariant being tested.

Applied to files:

  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
📚 Learning: 2026-03-02T10:14:16.036Z
Learnt from: Uri-Tauber
Repo: crosspoint-reader/crosspoint-reader PR: 1245
File: lib/Epub/Epub/Section.cpp:277-308
Timestamp: 2026-03-02T10:14:16.036Z
Learning: Guideline: Strengthen serialization::readString to defend against unbounded growth when reading from disk data. Implement and enforce a maximum allowed length (e.g., a configured or reasonable constant) and validate the incoming length before resizing or allocating. Audit all call sites (e.g., BookMetadataCache, TextBlock, KOReaderCredentialStore, Section cache readers) to ensure they do not rely on unbounded len-based resizing. If the readString API must remain, add internal safeguards (bounds checks, length validation, and error handling) so per-call-site validations are not required. Ensure Section cache files remain versioned (SECTION_FILE_VERSION) and parameter mismatches invalidate caches, but do not rely on unsafe allocations; prefer safe, bounded reads with explicit errors on invalid data.

Applied to files:

  • lib/Epub/Epub/hyphenation/Hyphenator.cpp

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
lib/Epub/Epub/hyphenation/Hyphenator.cpp (1)

144-148: Consider deduping by byteOffset alone for clarity.

The current unique predicate requires both byteOffset and requiresInsertedHyphen to match. While in practice the same offset shouldn't appear with different flag values (pattern breaks are interior, apostrophe breaks are at separators), deduping by offset only would be more defensive and clearer about intent.

♻️ Suggested simplification
   infos.erase(std::unique(infos.begin(), infos.end(),
                           [](const Hyphenator::BreakInfo& a, const Hyphenator::BreakInfo& b) {
-                            return a.byteOffset == b.byteOffset && a.requiresInsertedHyphen == b.requiresInsertedHyphen;
+                            return a.byteOffset == b.byteOffset;
                           }),
               infos.end());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/Epub/Epub/hyphenation/Hyphenator.cpp` around lines 144 - 148, The
deduplication currently used in the infos.erase(std::unique(...)) call compares
both Hyphenator::BreakInfo::byteOffset and requiresInsertedHyphen; change the
unique predicate to compare only byteOffset (i.e., return a.byteOffset ==
b.byteOffset) so duplicates are removed solely by offset for clarity and
defensiveness. Update the lambda passed to std::unique (the predicate used with
infos.begin()/infos.end()) to only compare byteOffset, leaving the surrounding
call to infos.erase(std::unique(...), infos.end()) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lib/Epub/Epub/hyphenation/Hyphenator.cpp`:
- Around line 144-148: The deduplication currently used in the
infos.erase(std::unique(...)) call compares both
Hyphenator::BreakInfo::byteOffset and requiresInsertedHyphen; change the unique
predicate to compare only byteOffset (i.e., return a.byteOffset == b.byteOffset)
so duplicates are removed solely by offset for clarity and defensiveness. Update
the lambda passed to std::unique (the predicate used with
infos.begin()/infos.end()) to only compare byteOffset, leaving the surrounding
call to infos.erase(std::unique(...), infos.end()) unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7a681b42-f2e9-4599-a790-cedd0fffcd82

📥 Commits

Reviewing files that changed from the base of the PR and between 2e739a6 and bf72acd.

📒 Files selected for processing (1)
  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: cppcheck
  • GitHub Check: build
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2026-02-19T12:17:05.421Z
Learnt from: Uri-Tauber
Repo: crosspoint-reader/crosspoint-reader PR: 988
File: lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp:649-661
Timestamp: 2026-02-19T12:17:05.421Z
Learning: In ChapterHtmlSlimParser.cpp, when computing footnote word indices in endElement() for footnote links, the wordIndex must be cumulative across the 750-word mid-paragraph flush boundary. The correct calculation is: `wordIndex = wordsExtractedInBlock + currentTextBlock->size()`, not just `currentTextBlock->size()`. This ensures footnotes attach to the page containing their actual anchor word, even after layoutAndExtractLines(false) has extracted and removed earlier words from the block.

Applied to files:

  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
📚 Learning: 2026-02-27T22:49:59.600Z
Learnt from: ngxson
Repo: crosspoint-reader/crosspoint-reader PR: 1218
File: src/activities/ActivityManager.cpp:254-265
Timestamp: 2026-02-27T22:49:59.600Z
Learning: In this codebase, assertions are always enabled (no NDEBUG). Use assert() to crash on programmer errors and surface logic bugs during development and in production builds. Do not rely on asserts for runtime error handling; they should enforce invariants that must always hold. Keep asserts side-effect free and inexpensive, and avoid relying on them for user-visible failures. Include <cassert> where appropriate and document the invariant being tested.

Applied to files:

  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
📚 Learning: 2026-03-02T10:14:16.036Z
Learnt from: Uri-Tauber
Repo: crosspoint-reader/crosspoint-reader PR: 1245
File: lib/Epub/Epub/Section.cpp:277-308
Timestamp: 2026-03-02T10:14:16.036Z
Learning: Guideline: Strengthen serialization::readString to defend against unbounded growth when reading from disk data. Implement and enforce a maximum allowed length (e.g., a configured or reasonable constant) and validate the incoming length before resizing or allocating. Audit all call sites (e.g., BookMetadataCache, TextBlock, KOReaderCredentialStore, Section cache readers) to ensure they do not rely on unbounded len-based resizing. If the readString API must remain, add internal safeguards (bounds checks, length validation, and error handling) so per-call-site validations are not required. Ensure Section cache files remain versioned (SECTION_FILE_VERSION) and parameter mismatches invalidate caches, but do not rely on unsafe allocations; prefer safe, bounded reads with explicit errors on invalid data.

Applied to files:

  • lib/Epub/Epub/hyphenation/Hyphenator.cpp
🔇 Additional comments (5)
lib/Epub/Epub/hyphenation/Hyphenator.cpp (5)

88-95: LGTM! Interior index validation properly addresses the previous review concern.

The assertion correctly catches programmer errors from breakIndexes returning boundary indices, and the subsequent guard ensures graceful recovery. This aligns with the codebase convention of using assert() for invariant enforcement.


102-134: LGTM! Contraction break logic correctly prevents stranding short clitics.

The minimum thresholds (kMinLeftSegmentLen=3, kMinRightSegmentLen=2) appropriately prevent problematic splits like "can' | t" or "l' | état" while allowing valid breaks like "all' | improvviso". The earlier review concern about English contractions is addressed.


163-170: LGTM!

Early detection of apostrophe separators is efficient and correctly gates the subsequent segmentation logic.


189-199: LGTM!

The integration of apostrophe contraction breaks alongside explicit hyphens is well-designed. Passing includeFallback=false for segments is appropriate since explicit hyphens already provide break points.


202-214: LGTM!

The apostrophe handling correctly segments words for per-segment hyphenation. Passing includeFallback to appendSegmentPatternBreaks ensures fallback breaks work within segments when requested. The caller gracefully handles an empty result.

Copy link
Copy Markdown
Member

@znelson znelson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks reasonable to me. Thanks for fixing the English contraction case. I think it'd be good to move forward with this and get user feedback around whether it's working as expected in languages with apostrophes in more common usage.

trilwu added a commit to trilwu/crosspet that referenced this pull request Mar 10, 2026
@drbourbon
Copy link
Copy Markdown
Contributor

Hope this gets merged soon, because it's a huge page rendering enhancement, especially when using big fonts with apostrophe based languages. Thanks!

IMG_1034

@znelson znelson requested a review from a team March 11, 2026 14:35
@znelson znelson merged commit 3dabd30 into crosspoint-reader:master Mar 11, 2026
6 checks passed
lukestein pushed a commit to lukestein/crosspoint-reader that referenced this pull request Mar 12, 2026
…er#1318)

## Summary

* **What is the goal of this PR?** Fixing / extending the hyphenation
logic to deal with words containing an apostophe as raised in crosspoint-reader#1186
* **What changes are included?**

## Additional Context

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**PARTIALLY**_ (as the
user provided a thorough analysis that I followed)
@jpirnay jpirnay deleted the fix-hyphen_apostrophe branch March 12, 2026 20:17
noel88 pushed a commit to noel88/crosspoint-reader-cjk that referenced this pull request Mar 13, 2026
Integrate upstream changes:
- fix: jpeg resource cleanup (crosspoint-reader#1320)
- feat: Kazakh language support (crosspoint-reader#1377)
- fix: lastSleepImage init edge case (crosspoint-reader#1360)
- chore: settings tab label change (crosspoint-reader#1325)
- fix: back button in settings (crosspoint-reader#1354)
- fix: apostrophe hyphenation (crosspoint-reader#1318)
- perf: font-compression improvements (crosspoint-reader#1056)
- fix: Spanish translations (crosspoint-reader#1338)
- fix: inter-word spacing rounding error (crosspoint-reader#1311)

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
@lukestein
Copy link
Copy Markdown
Contributor

This looks reasonable to me. Thanks for fixing the English contraction case. I think it'd be good to move forward with this and get user feedback around whether it's working as expected in languages with apostrophes in more common usage.

I see @znelson referred to "fixing the English contraction case" but alas @jpirnay I'm getting problems with contractions getting broken at the apostrophe. See screenshots in #1403.

BillionClaw pushed a commit to BillionClaw/crosspoint-reader that referenced this pull request Mar 15, 2026
PR crosspoint-reader#1318 added support for hyphenating words with apostrophes (Italian/French
contractions like 'all\'improvviso'). However, this introduced a regression
where English contractions like 'you\'re', 'what\'s' were incorrectly broken
at the apostrophe.

The fix adds detection for common English contraction suffixes ('s, 're, 've,
'll, 'd, 't, 'm) and prevents line breaks at those positions while still
allowing breaks for Italian/French-style contractions.

Fixes crosspoint-reader#1403
@znelson
Copy link
Copy Markdown
Member

znelson commented Mar 16, 2026

@lukestein indeed, should be a simple tweak, hopefully 🙂

whale-n pushed a commit to whale-n/njwiv-xt that referenced this pull request Mar 17, 2026
…er#1318)

## Summary

* **What is the goal of this PR?** Fixing / extending the hyphenation
logic to deal with words containing an apostophe as raised in crosspoint-reader#1186
* **What changes are included?**

## Additional Context

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**PARTIALLY**_ (as the
user provided a thorough analysis that I followed)
lukestein pushed a commit to lukestein/crosspoint-reader that referenced this pull request Mar 18, 2026
…er#1318)

## Summary

* **What is the goal of this PR?** Fixing / extending the hyphenation
logic to deal with words containing an apostophe as raised in crosspoint-reader#1186
* **What changes are included?**

## Additional Context

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**PARTIALLY**_ (as the
user provided a thorough analysis that I followed)
lukestein pushed a commit to lukestein/crosspoint-reader that referenced this pull request Mar 19, 2026
…er#1318)

## Summary

* **What is the goal of this PR?** Fixing / extending the hyphenation
logic to deal with words containing an apostophe as raised in crosspoint-reader#1186
* **What changes are included?**

## Additional Context

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**PARTIALLY**_ (as the
user provided a thorough analysis that I followed)
znelson added a commit that referenced this pull request Apr 3, 2026
## Summary

It's been a little while since the last release, but the community has
been incredibly busy. With 155 changes from 48 contributors (30 of which
were new!), there was a lot to cover. Here are some of the highlights:

**🔤 Kerning, Ligatures, and Font Improvements**
Text rendering gets a significant upgrade with proper kerning and
ligature support, fixed-point fractional x-advance for more accurate
character placement, and font compression improvements that reduce flash
usage.

**📝 Footnotes**
Footnote anchor navigation lets you select a footnote reference and jump
to the footnote text, then jump back. Slim footnotes support is also
available for books that use inline footnotes.

**📖 EPUB Optimizer**
A new integrated EPUB optimizer can clean up and reprocess books for
better compatibility with the reader, directly from the device.

**🔋 Battery Charging Indicator**
You can now see when your device is actively charging, with a visual
indicator on the battery icon.

**💾 Crash Diagnostics**
When something goes wrong, the firmware now dumps a crash report to the
SD card — even without USB plugged in. This makes it much easier to
report and diagnose issues.

**🌐 New Languages**
The community continues to expand language support. New in this release:
Turkish, Danish, Finnish, Polish, Dutch, Belarusian, Italian, Ukrainian,
Romanian, Catalan, Vietnamese, and Kazakh — along with significant
improvements to existing translations.

**📂 File Management**
Multi-select file deletion, BMP image viewer in the file browser, hidden
directory browsing, and long-click file deletion from the file browser.

**⚡ Performance**
Under the hood, text layout switched from `std::list` to `std::vector`,
HTML entity lookups are now O(log(n)), font rendering is faster, image
decode is 5-20% faster with per-pixel overhead eliminated, and multiple
string allocation hot paths were eliminated. Pre-indexing of the next
chapter also reduces page-turn latency at chapter boundaries.

---

Along with all of the above, there are many other additions including
**WebDAV support**, **auto page turn**, **QR code for current page**,
**split status bar settings**, **screenshot capture**, **JSON-based
settings migration**, **light/dark theme groundwork**, and a long list
of stability fixes and translation improvements.

## What's Changed
### Features
* feat: Support for kerning and ligatures by @znelson in
#873
* feat: footnote anchor navigation by @Uri-Tauber in
#1245
* feat: slim footnotes support by @Uri-Tauber in
#1031
* feat: integrated epub optimizer by @zgredex and @pablohc in
#1224
* feat: battery charging indicator (mirroring PR #537) by @jpirnay in
#1427
* feat: dump crash report to sdcard by @ngxson in
#1145
* feat: Implement silent pre-indexing for the next chapter in
EpubReaderActivity by @LSTAR1900 in
#979
* feat: upgrade platform and support webdav by @dexif in
#1047
* feat: Auto Page Turn for Epub Reader by @GenesiaW in
#1219
* feat: enhance file deletion functionality with multi-select by
@Jessica765 in
#682
* feat: Long Click for File Deletion through File Browser by @Levrk in
#909
* feat: Take screenshots by @el in
#759
* feat: Current page as QR by @el in
#1099
* feat: Download links for web server by @el in
#1039
* feat: Added BmpViewer activity for viewing .bmp images in file browser
by @Levrk in
#887
* feat: User setting for image display by @jpirnay in
#1291
* feat: Show hidden directories in browser by @jpirnay in
#1288
* feat: Prefer ".sleep" over "sleep" for custom image directory by
@jpirnay in
#948
* feat: Allow a local configuration file for custom compiles by @jpirnay
in #879
* feat: Migrate binary settings to json by @jpirnay in
#920
* feat: split status bar setting by @whyte-j in
#733
* feat: wrapped text in GfxRender, implemented in themes so far by
@iandchasse in
#1141
* feat: Themed language screen by @CaptainFrito in
#1020
* feat: set WiFi hostname to CrossPoint-Reader-XXXXXXXXXXXX by @dexif in
#1107
* feat: Add maxAlloc to memory information by @jpirnay in
#1152
* feat: replace picojpeg with JPEGDEC for JPEG image decoding by
@martinbrook in
#1136
* feat: Add git branch to version information on settings screen by
@jpirnay in
#1225
* feat: sort languages in selection menu by @ariel-lindemann in
#1071
* feat: Latin Extended-B European glyphs by @znelson in
#1157
* feat: Latin Extended-B European glyphs by @znelson in
#1167
* feat: Vietnamese glyphs support by @danoooob in
#1147
* feat: add Turkish translation by @barbarhan in
#1192
* feat: add full Danish translation by @hajisan in
#1146
* feat: Add Finnish translations by @plahteenlahti in
#1133
* feat: Add Polish Language by @th0m4sek in
#1155
* feat: add Dutch translation by @basvdploeg in
#1204
* feat: add Belarusian translation by @dexif in
#1120
* feat: Add full Italian translations by @andreaturchet in
#1144
* feat: add Ukrainian translation by @mirus-ua in
#1065
* feat: Add Kazakh (kk) language support by @fsocietyipa in
#1377
* feat: added Romanian strings by @ariel-lindemann in
#987
* feat: add Catalan strings by @angeldenom in
#1049
* feat: Make directories stand out more in local file browser: "[dir]"
instead of "dir" by @jpirnay in
#1339
* feat: Add Polish strings for commits #1219,#1169,#1031 +tweaks by
@th0m4sek in
#1227
* feat: Polish translation tweaks by @th0m4sek in
#1193
### Fixes
* fix: Fix img layout issue / support CSS display:none for elements and
images by @jpirnay in
#1443
* fix: Overlapping battery percentage on image pages with anti-aliasing
by @znelson in
#1452
* fix: Fix prewarm perf when a page contains many styles by
@adriancaruana in
#1451
* fix: use sleep routine from the original firmware by @ngxson in
#1298
* fix: Prevent line breaks on common English contractions by @znelson in
#1405
* fix: Build with -fno-exceptions by @znelson in
#1412
* fix: Reduce flash usage by cleaning up I18n translations by @steka in
#1401
* fix: jpeg resource cleanup by @jpirnay in
#1320
* fix: back button in settings returns to tab bar first by @Cache8063 in
#1354
* fix: Init lastSleepImage (edge case) by @jpirnay in
#1360
* fix: Add special handling for apostrophe hyphenation by @jpirnay in
#1318
* fix: Fix inter-word spacing rounding error in text layout by @znelson
in #1311
* fix: load access fault crash by @Uri-Tauber in
#1370
* fix: Fix bootloop logging crash by @jpirnay in
#1357
* fix: dump crash log without usb plugged, bump release log to INFO by
@ngxson in
#1332
* fix: avoid zip filename overflow by @jpirnay in
#1321
* fix: Hanging indent (negative text-indent) and em-unit sizing by
@jpirnay in
#1229
* fix: Use fixed-point fractional x-advance and kerning for better text
layout by @znelson in
#1168
* fix: use HTTPClient::writeToStream for downloading files from OPDS by
@osteotek in
#1207
* fix: make file system operations thread-safe (HalFile) by @ngxson in
#1212
* fix: properly implement requestUpdateAndWait() by @ngxson in
#1218
* fix: prevent infinite render loop in Calibre Wireless after file
transfer by @pablohc in
#1070
* fix: WiFi lifecycle and hyphenation heap defragmentation for KOReader
sync by @jpirnay in
#1151
* fix: Fix coverRendered flag by @jpirnay in
#1154
* fix: Handle non-ASCII characters in sanitizeFilename by @znelson in
#1132
* fix: Update activity was missing "Back" button label by @znelson in
#1128
* fix: force auto-hinting for Bookerly to fix inconsistent stem widths
by @adriancaruana in
#1098
* fix: image centering bleed by @martinbrook in
#1096
* fix: double free WebDAVHandler by @ngxson in
#1093
* fix: Consider extra quotation styles when hyphenating quoted words by
@cbix in
#1077
* fix: acquire power lock before sleeping by @ngxson in
#1125
* fix: Unify inconsistent Wi-Fi/WiFi in Czech translation by @pepastach
in #1138
* fix: sdfat warning about redefinition of macro by @ngxson in
#1135
* fix: Close leaked file descriptors in SleepActivity and web server by
@brbla in
#869
* fix: Enable DESTRUCTOR_CLOSES_FILE flag by @daveallie in
#1075
* fix: Change "UI Font Size" to "Reader Font Size" by @divinitycove in
#1171
* fix: Hide unusable button hints when viewing empty directory by @Levrk
in #1253
* fix: broken translations in status bar settings by @ariel-lindemann in
#1188
* fix: clarity issue with ambiguous string `SET` by @ariel-lindemann in
#1169
* fix: Crash (Load access fault) when indexing chapters containing
characters unsupported by bold/italic font variants by @Uri-Tauber in
#997
* fix: Increase PNGdec buffer size to support wide images by @osteotek
in #995
* fix: Use HalPowerManager for battery percentage by @vjapolitzer in
#1005
* fix: Fix dangling pointer by @Uri-Tauber in
#1010
* fix: re-implementing Cover Outlines for the new Lyra Themes by @Levrk
in #1017
* fix: use double FAST_REFRESH to prevent washout on large grey images
by @martinbrook in
#957
* fix: Fixed Image Sizing When No Width is Set by @DestinySpeaker in
#1002
* fix: Strip unused CSS rules by @daveallie in
#1014
* fix: continue reading card classic theme by @pablohc in
#990
* fix: Destroy CSS Cache file when invalid by @daveallie in
#1018
* fix: Shorten "Forget Wifi" button labels to fit on button by
@lukestein in
#1045
* fix: improve Spanish translations by @pablohc in
#1054
* fix: Fixed book title in home screen by @DestinySpeaker in
#1013
* fix: Fix hyphenation and rendering of decomposed characters by
@jpirnay in
#1037
* fix: Improve and add Spanish translations by @DaniPhii in
#1338
* fix: improve and add Spanish translations by @DaniPhii in
#1254
* fix: improve and add Swedish translations by @steka in
#1317
* fix: Extend missing / amend existing German translations by @jpirnay
in #1226
* fix: update french.yaml file to have a better French translation of
the CFW by @Spigaw in
#1130
* fix: added romanian translation to new strings by @ariel-lindemann in
#1105
* fix: add missing romanian strings by @ariel-lindemann in
#1187
* fix: add new Ukrainian translation line for STR_SCREENSHOT_BUTTON by
@mirus-ua in
#1149
* fix: Dutch translation prefix correction by @basvdploeg in
#1223
* fix: Small typo in i18n.md regarding C++ identifiers by
@victordomingos in
#1210
* fix: typo in USER_GUIDE.md by @arnaugamez in
#1036
* fix: add missing keyboard metrics to Lyra3CoversTheme by @dexif in
#1101

### Internal
* perf: font-compression improvements by @adriancaruana in
#1056
* perf: Improve font drawing performance by @jpirnay in
#978
* perf: Replace std::list with std::vector in text layout by @znelson in
#1038
* perf: Optimize HTML entities lookup to O(log(n)) by @Uri-Tauber in
#1194
* perf: UITheme::getMetrics const and const-ref usage by @znelson in
#1094
* perf: Avoid creating strings for file extension checks by @znelson in
#1303
* perf: Eliminate per-pixel overheads in image rendering by @martinbrook
in #1293
* perf: Update github actions for optimal performance with pioarduino by
@Jason2866 in
#1080
* style: Phase 1 - Simple light dark themes by @cdmoro in
#1006
* refactor: implement ActivityManager by @ngxson in
#1016
* refactor: Simplify REPLACEMENT_GLYPH fallback by @znelson in
#1119
* refactor: Simplify new setting introduction by @jpirnay in
#1086
* refactor: Use std binary search algorithms for font lookups by
@znelson in
#1202
* refactor: rename MyLibrary to FileBrowser by @osteotek in
#1260
* refactor: Avoid rebuilding cache path strings by @znelson in
#1300
* refactor: reader utils by @Uri-Tauber in
#1329
* chore: Remove miniz and modularise inflation logic by @daveallie in
#1073
* chore: Resolve several build warnings by @daveallie in
#1076
* chore: Removed generated language headers by @znelson in
#1156
* chore: Added generated lang headers to .gitignore by @znelson in
#1158
* chore: remove redundant xTaskCreate by @ngxson in
#1264
* chore: Removed unused PlatformIO include directory placeholder by
@znelson in
#1417
* chore: micro-optimisation: early exit on fillUncompressedSizes by
@jpirnay in
#1322
* chore: change label while on settings tab actions by @jpirnay in
#1325
* chore: add firmware size history script by @znelson in
#1235
* chore: Add powershell script for clang-formatting by @jpirnay in
#1472
* chore: Removed unused ConfirmationActivity member by @znelson in
#1234
* chore: Update russian.yaml by @madebyKir in
#1198
* chore: new Ukrainian translation lines by @mirus-ua in
#1199
* chore: new Ukrainian localization strings by @mirus-ua in
#1270
* chore: Polish localization for STR_DELETE by @JonaszPotoniec in
#1323
* chore: Image settings Polish localization by @znelson in
#1299
* chore: add missing Catalan strings by @angeldenom in
#1302
* chore: add missing translations for Romanian by @ariel-lindemann in
#1265
* chore: Add Portuguese (Portugal) translator to the list by
@victordomingos in
#1211
* chore: Reduce flash usage by cleaning up I18n translations by @steka
in #1401
* docs: Add lightweight contributor onboarding documentation by @bilalix
in #894
* docs: ActivityManager migration guide by @znelson in
#1222
* docs: USER_GUIDE.md update for 1.1.0 by @divinitycove in
#1108
* docs: add quick KOReader sync setup guide by @wjhrdy in
#1181
* docs: image support marked as completed by @ariel-lindemann in
#1008
* feat: aiagent context definition by @jpirnay in
#922
* chore: Update SKILL.md to reflect generated i18n files are gitignored
by @znelson in
#1423
* fix: ActivityManager tweaks by @znelson in
#1220
* fix: Correct relative file paths in SKILL.md documentation by @pablohc
in #1304
* fix: add Technically Unsupported section to SCOPE.md by @Uri-Tauber in
#1295

## New Contributors
* @DestinySpeaker made their first contribution in
#1002
* @arnaugamez made their first contribution in
#1036
* @angeldenom made their first contribution in
#1049
* @cdmoro made their first contribution in
#1006
* @bilalix made their first contribution in
#894
* @Jessica765 made their first contribution in
#682
* @brbla made their first contribution in
#869
* @dexif made their first contribution in
#1047
* @mirus-ua made their first contribution in
#1065
* @cbix made their first contribution in
#1077
* @divinitycove made their first contribution in
#1108
* @pepastach made their first contribution in
#1138
* @Jason2866 made their first contribution in
#1080
* @andreaturchet made their first contribution in
#1144
* @Spigaw made their first contribution in
#1130
* @iandchasse made their first contribution in
#1141
* @th0m4sek made their first contribution in
#1155
* @plahteenlahti made their first contribution in
#1133
* @hajisan made their first contribution in
#1146
* @madebyKir made their first contribution in
#1198
* @victordomingos made their first contribution in
#1210
* @basvdploeg made their first contribution in
#1204
* @wjhrdy made their first contribution in
#1181
* @DaniPhii made their first contribution in
#1254
* @steka made their first contribution in
#1317
* @barbarhan made their first contribution in
#1192
* @JonaszPotoniec made their first contribution in
#1323
* @Cache8063 made their first contribution in
#1354
* @fsocietyipa made their first contribution in
#1377
* @LSTAR1900 made their first contribution in
#979
* @zgredex made their first contribution in
#1224

**Full Changelog**:
1.1.1...release/1.2.0

---------

Co-authored-by: jpirnay <jens@pirnay.com>
Co-authored-by: Dani Poveda <daniphii@outlook.com>
Co-authored-by: Baris Albayrak <80099286+barbarhan@users.noreply.github.com>
Co-authored-by: Barış Albayrak <barisa@pop-os.lan>
Co-authored-by: Stefan Blixten Karlsson <sbkarlsson@gmail.com>
Co-authored-by: Àngel <153315454+angeldenom@users.noreply.github.com>
Co-authored-by: Jonasz Potoniec <jonasz@potoniec.eu>
Co-authored-by: Егор Мартынов <martynovegorOF@yandex.ru>
Co-authored-by: Mirus <mirusim@gmail.com>
Co-authored-by: Spigaw <73850535+Spigaw@users.noreply.github.com>
Co-authored-by: ariel-lindemann <41641978+ariel-lindemann@users.noreply.github.com>
Co-authored-by: Nima Salami <54304457+hajisan@users.noreply.github.com>
Co-authored-by: Arthur Tazhitdinov <lisnake@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Bas van der Ploeg <bas@basvanderploeg.nl>
Co-authored-by: martin brook <martin.brook100@googlemail.com>
Unintendedsideeffects pushed a commit to Unintendedsideeffects/ForkDrift-crosspointReader that referenced this pull request Apr 4, 2026
It's been a little while since the last release, but the community has
been incredibly busy. With 155 changes from 48 contributors (30 of which
were new!), there was a lot to cover. Here are some of the highlights:

**🔤 Kerning, Ligatures, and Font Improvements**
Text rendering gets a significant upgrade with proper kerning and
ligature support, fixed-point fractional x-advance for more accurate
character placement, and font compression improvements that reduce flash
usage.

**📝 Footnotes**
Footnote anchor navigation lets you select a footnote reference and jump
to the footnote text, then jump back. Slim footnotes support is also
available for books that use inline footnotes.

**📖 EPUB Optimizer**
A new integrated EPUB optimizer can clean up and reprocess books for
better compatibility with the reader, directly from the device.

**🔋 Battery Charging Indicator**
You can now see when your device is actively charging, with a visual
indicator on the battery icon.

**💾 Crash Diagnostics**
When something goes wrong, the firmware now dumps a crash report to the
SD card — even without USB plugged in. This makes it much easier to
report and diagnose issues.

**🌐 New Languages**
The community continues to expand language support. New in this release:
Turkish, Danish, Finnish, Polish, Dutch, Belarusian, Italian, Ukrainian,
Romanian, Catalan, Vietnamese, and Kazakh — along with significant
improvements to existing translations.

**📂 File Management**
Multi-select file deletion, BMP image viewer in the file browser, hidden
directory browsing, and long-click file deletion from the file browser.

**⚡ Performance**
Under the hood, text layout switched from `std::list` to `std::vector`,
HTML entity lookups are now O(log(n)), font rendering is faster, image
decode is 5-20% faster with per-pixel overhead eliminated, and multiple
string allocation hot paths were eliminated. Pre-indexing of the next
chapter also reduces page-turn latency at chapter boundaries.

---

Along with all of the above, there are many other additions including
**WebDAV support**, **auto page turn**, **QR code for current page**,
**split status bar settings**, **screenshot capture**, **JSON-based
settings migration**, **light/dark theme groundwork**, and a long list
of stability fixes and translation improvements.

* feat: Support for kerning and ligatures by @znelson in
crosspoint-reader#873
* feat: footnote anchor navigation by @Uri-Tauber in
crosspoint-reader#1245
* feat: slim footnotes support by @Uri-Tauber in
crosspoint-reader#1031
* feat: integrated epub optimizer by @zgredex and @pablohc in
crosspoint-reader#1224
* feat: battery charging indicator (mirroring PR crosspoint-reader#537) by @jpirnay in
crosspoint-reader#1427
* feat: dump crash report to sdcard by @ngxson in
crosspoint-reader#1145
* feat: Implement silent pre-indexing for the next chapter in
EpubReaderActivity by @LSTAR1900 in
crosspoint-reader#979
* feat: upgrade platform and support webdav by @dexif in
crosspoint-reader#1047
* feat: Auto Page Turn for Epub Reader by @GenesiaW in
crosspoint-reader#1219
* feat: enhance file deletion functionality with multi-select by
@Jessica765 in
crosspoint-reader#682
* feat: Long Click for File Deletion through File Browser by @Levrk in
crosspoint-reader#909
* feat: Take screenshots by @el in
crosspoint-reader#759
* feat: Current page as QR by @el in
crosspoint-reader#1099
* feat: Download links for web server by @el in
crosspoint-reader#1039
* feat: Added BmpViewer activity for viewing .bmp images in file browser
by @Levrk in
crosspoint-reader#887
* feat: User setting for image display by @jpirnay in
crosspoint-reader#1291
* feat: Show hidden directories in browser by @jpirnay in
crosspoint-reader#1288
* feat: Prefer ".sleep" over "sleep" for custom image directory by
@jpirnay in
crosspoint-reader#948
* feat: Allow a local configuration file for custom compiles by @jpirnay
in crosspoint-reader#879
* feat: Migrate binary settings to json by @jpirnay in
crosspoint-reader#920
* feat: split status bar setting by @whyte-j in
crosspoint-reader#733
* feat: wrapped text in GfxRender, implemented in themes so far by
@iandchasse in
crosspoint-reader#1141
* feat: Themed language screen by @CaptainFrito in
crosspoint-reader#1020
* feat: set WiFi hostname to CrossPoint-Reader-XXXXXXXXXXXX by @dexif in
crosspoint-reader#1107
* feat: Add maxAlloc to memory information by @jpirnay in
crosspoint-reader#1152
* feat: replace picojpeg with JPEGDEC for JPEG image decoding by
@martinbrook in
crosspoint-reader#1136
* feat: Add git branch to version information on settings screen by
@jpirnay in
crosspoint-reader#1225
* feat: sort languages in selection menu by @ariel-lindemann in
crosspoint-reader#1071
* feat: Latin Extended-B European glyphs by @znelson in
crosspoint-reader#1157
* feat: Latin Extended-B European glyphs by @znelson in
crosspoint-reader#1167
* feat: Vietnamese glyphs support by @danoooob in
crosspoint-reader#1147
* feat: add Turkish translation by @barbarhan in
crosspoint-reader#1192
* feat: add full Danish translation by @hajisan in
crosspoint-reader#1146
* feat: Add Finnish translations by @plahteenlahti in
crosspoint-reader#1133
* feat: Add Polish Language by @th0m4sek in
crosspoint-reader#1155
* feat: add Dutch translation by @basvdploeg in
crosspoint-reader#1204
* feat: add Belarusian translation by @dexif in
crosspoint-reader#1120
* feat: Add full Italian translations by @andreaturchet in
crosspoint-reader#1144
* feat: add Ukrainian translation by @mirus-ua in
crosspoint-reader#1065
* feat: Add Kazakh (kk) language support by @fsocietyipa in
crosspoint-reader#1377
* feat: added Romanian strings by @ariel-lindemann in
crosspoint-reader#987
* feat: add Catalan strings by @angeldenom in
crosspoint-reader#1049
* feat: Make directories stand out more in local file browser: "[dir]"
instead of "dir" by @jpirnay in
crosspoint-reader#1339
* feat: Add Polish strings for commits crosspoint-reader#1219,crosspoint-reader#1169,crosspoint-reader#1031 +tweaks by
@th0m4sek in
crosspoint-reader#1227
* feat: Polish translation tweaks by @th0m4sek in
crosspoint-reader#1193
* fix: Fix img layout issue / support CSS display:none for elements and
images by @jpirnay in
crosspoint-reader#1443
* fix: Overlapping battery percentage on image pages with anti-aliasing
by @znelson in
crosspoint-reader#1452
* fix: Fix prewarm perf when a page contains many styles by
@adriancaruana in
crosspoint-reader#1451
* fix: use sleep routine from the original firmware by @ngxson in
crosspoint-reader#1298
* fix: Prevent line breaks on common English contractions by @znelson in
crosspoint-reader#1405
* fix: Build with -fno-exceptions by @znelson in
crosspoint-reader#1412
* fix: Reduce flash usage by cleaning up I18n translations by @steka in
crosspoint-reader#1401
* fix: jpeg resource cleanup by @jpirnay in
crosspoint-reader#1320
* fix: back button in settings returns to tab bar first by @Cache8063 in
crosspoint-reader#1354
* fix: Init lastSleepImage (edge case) by @jpirnay in
crosspoint-reader#1360
* fix: Add special handling for apostrophe hyphenation by @jpirnay in
crosspoint-reader#1318
* fix: Fix inter-word spacing rounding error in text layout by @znelson
in crosspoint-reader#1311
* fix: load access fault crash by @Uri-Tauber in
crosspoint-reader#1370
* fix: Fix bootloop logging crash by @jpirnay in
crosspoint-reader#1357
* fix: dump crash log without usb plugged, bump release log to INFO by
@ngxson in
crosspoint-reader#1332
* fix: avoid zip filename overflow by @jpirnay in
crosspoint-reader#1321
* fix: Hanging indent (negative text-indent) and em-unit sizing by
@jpirnay in
crosspoint-reader#1229
* fix: Use fixed-point fractional x-advance and kerning for better text
layout by @znelson in
crosspoint-reader#1168
* fix: use HTTPClient::writeToStream for downloading files from OPDS by
@osteotek in
crosspoint-reader#1207
* fix: make file system operations thread-safe (HalFile) by @ngxson in
crosspoint-reader#1212
* fix: properly implement requestUpdateAndWait() by @ngxson in
crosspoint-reader#1218
* fix: prevent infinite render loop in Calibre Wireless after file
transfer by @pablohc in
crosspoint-reader#1070
* fix: WiFi lifecycle and hyphenation heap defragmentation for KOReader
sync by @jpirnay in
crosspoint-reader#1151
* fix: Fix coverRendered flag by @jpirnay in
crosspoint-reader#1154
* fix: Handle non-ASCII characters in sanitizeFilename by @znelson in
crosspoint-reader#1132
* fix: Update activity was missing "Back" button label by @znelson in
crosspoint-reader#1128
* fix: force auto-hinting for Bookerly to fix inconsistent stem widths
by @adriancaruana in
crosspoint-reader#1098
* fix: image centering bleed by @martinbrook in
crosspoint-reader#1096
* fix: double free WebDAVHandler by @ngxson in
crosspoint-reader#1093
* fix: Consider extra quotation styles when hyphenating quoted words by
@cbix in
crosspoint-reader#1077
* fix: acquire power lock before sleeping by @ngxson in
crosspoint-reader#1125
* fix: Unify inconsistent Wi-Fi/WiFi in Czech translation by @pepastach
in crosspoint-reader#1138
* fix: sdfat warning about redefinition of macro by @ngxson in
crosspoint-reader#1135
* fix: Close leaked file descriptors in SleepActivity and web server by
@brbla in
crosspoint-reader#869
* fix: Enable DESTRUCTOR_CLOSES_FILE flag by @daveallie in
crosspoint-reader#1075
* fix: Change "UI Font Size" to "Reader Font Size" by @divinitycove in
crosspoint-reader#1171
* fix: Hide unusable button hints when viewing empty directory by @Levrk
in crosspoint-reader#1253
* fix: broken translations in status bar settings by @ariel-lindemann in
crosspoint-reader#1188
* fix: clarity issue with ambiguous string `SET` by @ariel-lindemann in
crosspoint-reader#1169
* fix: Crash (Load access fault) when indexing chapters containing
characters unsupported by bold/italic font variants by @Uri-Tauber in
crosspoint-reader#997
* fix: Increase PNGdec buffer size to support wide images by @osteotek
in crosspoint-reader#995
* fix: Use HalPowerManager for battery percentage by @vjapolitzer in
crosspoint-reader#1005
* fix: Fix dangling pointer by @Uri-Tauber in
crosspoint-reader#1010
* fix: re-implementing Cover Outlines for the new Lyra Themes by @Levrk
in crosspoint-reader#1017
* fix: use double FAST_REFRESH to prevent washout on large grey images
by @martinbrook in
crosspoint-reader#957
* fix: Fixed Image Sizing When No Width is Set by @DestinySpeaker in
crosspoint-reader#1002
* fix: Strip unused CSS rules by @daveallie in
crosspoint-reader#1014
* fix: continue reading card classic theme by @pablohc in
crosspoint-reader#990
* fix: Destroy CSS Cache file when invalid by @daveallie in
crosspoint-reader#1018
* fix: Shorten "Forget Wifi" button labels to fit on button by
@lukestein in
crosspoint-reader#1045
* fix: improve Spanish translations by @pablohc in
crosspoint-reader#1054
* fix: Fixed book title in home screen by @DestinySpeaker in
crosspoint-reader#1013
* fix: Fix hyphenation and rendering of decomposed characters by
@jpirnay in
crosspoint-reader#1037
* fix: Improve and add Spanish translations by @DaniPhii in
crosspoint-reader#1338
* fix: improve and add Spanish translations by @DaniPhii in
crosspoint-reader#1254
* fix: improve and add Swedish translations by @steka in
crosspoint-reader#1317
* fix: Extend missing / amend existing German translations by @jpirnay
in crosspoint-reader#1226
* fix: update french.yaml file to have a better French translation of
the CFW by @Spigaw in
crosspoint-reader#1130
* fix: added romanian translation to new strings by @ariel-lindemann in
crosspoint-reader#1105
* fix: add missing romanian strings by @ariel-lindemann in
crosspoint-reader#1187
* fix: add new Ukrainian translation line for STR_SCREENSHOT_BUTTON by
@mirus-ua in
crosspoint-reader#1149
* fix: Dutch translation prefix correction by @basvdploeg in
crosspoint-reader#1223
* fix: Small typo in i18n.md regarding C++ identifiers by
@victordomingos in
crosspoint-reader#1210
* fix: typo in USER_GUIDE.md by @arnaugamez in
crosspoint-reader#1036
* fix: add missing keyboard metrics to Lyra3CoversTheme by @dexif in
crosspoint-reader#1101

* perf: font-compression improvements by @adriancaruana in
crosspoint-reader#1056
* perf: Improve font drawing performance by @jpirnay in
crosspoint-reader#978
* perf: Replace std::list with std::vector in text layout by @znelson in
crosspoint-reader#1038
* perf: Optimize HTML entities lookup to O(log(n)) by @Uri-Tauber in
crosspoint-reader#1194
* perf: UITheme::getMetrics const and const-ref usage by @znelson in
crosspoint-reader#1094
* perf: Avoid creating strings for file extension checks by @znelson in
crosspoint-reader#1303
* perf: Eliminate per-pixel overheads in image rendering by @martinbrook
in crosspoint-reader#1293
* perf: Update github actions for optimal performance with pioarduino by
@Jason2866 in
crosspoint-reader#1080
* style: Phase 1 - Simple light dark themes by @cdmoro in
crosspoint-reader#1006
* refactor: implement ActivityManager by @ngxson in
crosspoint-reader#1016
* refactor: Simplify REPLACEMENT_GLYPH fallback by @znelson in
crosspoint-reader#1119
* refactor: Simplify new setting introduction by @jpirnay in
crosspoint-reader#1086
* refactor: Use std binary search algorithms for font lookups by
@znelson in
crosspoint-reader#1202
* refactor: rename MyLibrary to FileBrowser by @osteotek in
crosspoint-reader#1260
* refactor: Avoid rebuilding cache path strings by @znelson in
crosspoint-reader#1300
* refactor: reader utils by @Uri-Tauber in
crosspoint-reader#1329
* chore: Remove miniz and modularise inflation logic by @daveallie in
crosspoint-reader#1073
* chore: Resolve several build warnings by @daveallie in
crosspoint-reader#1076
* chore: Removed generated language headers by @znelson in
crosspoint-reader#1156
* chore: Added generated lang headers to .gitignore by @znelson in
crosspoint-reader#1158
* chore: remove redundant xTaskCreate by @ngxson in
crosspoint-reader#1264
* chore: Removed unused PlatformIO include directory placeholder by
@znelson in
crosspoint-reader#1417
* chore: micro-optimisation: early exit on fillUncompressedSizes by
@jpirnay in
crosspoint-reader#1322
* chore: change label while on settings tab actions by @jpirnay in
crosspoint-reader#1325
* chore: add firmware size history script by @znelson in
crosspoint-reader#1235
* chore: Add powershell script for clang-formatting by @jpirnay in
crosspoint-reader#1472
* chore: Removed unused ConfirmationActivity member by @znelson in
crosspoint-reader#1234
* chore: Update russian.yaml by @madebyKir in
crosspoint-reader#1198
* chore: new Ukrainian translation lines by @mirus-ua in
crosspoint-reader#1199
* chore: new Ukrainian localization strings by @mirus-ua in
crosspoint-reader#1270
* chore: Polish localization for STR_DELETE by @JonaszPotoniec in
crosspoint-reader#1323
* chore: Image settings Polish localization by @znelson in
crosspoint-reader#1299
* chore: add missing Catalan strings by @angeldenom in
crosspoint-reader#1302
* chore: add missing translations for Romanian by @ariel-lindemann in
crosspoint-reader#1265
* chore: Add Portuguese (Portugal) translator to the list by
@victordomingos in
crosspoint-reader#1211
* chore: Reduce flash usage by cleaning up I18n translations by @steka
in crosspoint-reader#1401
* docs: Add lightweight contributor onboarding documentation by @bilalix
in crosspoint-reader#894
* docs: ActivityManager migration guide by @znelson in
crosspoint-reader#1222
* docs: USER_GUIDE.md update for 1.1.0 by @divinitycove in
crosspoint-reader#1108
* docs: add quick KOReader sync setup guide by @wjhrdy in
crosspoint-reader#1181
* docs: image support marked as completed by @ariel-lindemann in
crosspoint-reader#1008
* feat: aiagent context definition by @jpirnay in
crosspoint-reader#922
* chore: Update SKILL.md to reflect generated i18n files are gitignored
by @znelson in
crosspoint-reader#1423
* fix: ActivityManager tweaks by @znelson in
crosspoint-reader#1220
* fix: Correct relative file paths in SKILL.md documentation by @pablohc
in crosspoint-reader#1304
* fix: add Technically Unsupported section to SCOPE.md by @Uri-Tauber in
crosspoint-reader#1295

* @DestinySpeaker made their first contribution in
crosspoint-reader#1002
* @arnaugamez made their first contribution in
crosspoint-reader#1036
* @angeldenom made their first contribution in
crosspoint-reader#1049
* @cdmoro made their first contribution in
crosspoint-reader#1006
* @bilalix made their first contribution in
crosspoint-reader#894
* @Jessica765 made their first contribution in
crosspoint-reader#682
* @brbla made their first contribution in
crosspoint-reader#869
* @dexif made their first contribution in
crosspoint-reader#1047
* @mirus-ua made their first contribution in
crosspoint-reader#1065
* @cbix made their first contribution in
crosspoint-reader#1077
* @divinitycove made their first contribution in
crosspoint-reader#1108
* @pepastach made their first contribution in
crosspoint-reader#1138
* @Jason2866 made their first contribution in
crosspoint-reader#1080
* @andreaturchet made their first contribution in
crosspoint-reader#1144
* @Spigaw made their first contribution in
crosspoint-reader#1130
* @iandchasse made their first contribution in
crosspoint-reader#1141
* @th0m4sek made their first contribution in
crosspoint-reader#1155
* @plahteenlahti made their first contribution in
crosspoint-reader#1133
* @hajisan made their first contribution in
crosspoint-reader#1146
* @madebyKir made their first contribution in
crosspoint-reader#1198
* @victordomingos made their first contribution in
crosspoint-reader#1210
* @basvdploeg made their first contribution in
crosspoint-reader#1204
* @wjhrdy made their first contribution in
crosspoint-reader#1181
* @DaniPhii made their first contribution in
crosspoint-reader#1254
* @steka made their first contribution in
crosspoint-reader#1317
* @barbarhan made their first contribution in
crosspoint-reader#1192
* @JonaszPotoniec made their first contribution in
crosspoint-reader#1323
* @Cache8063 made their first contribution in
crosspoint-reader#1354
* @fsocietyipa made their first contribution in
crosspoint-reader#1377
* @LSTAR1900 made their first contribution in
crosspoint-reader#979
* @zgredex made their first contribution in
crosspoint-reader#1224

**Full Changelog**:
crosspoint-reader/crosspoint-reader@1.1.1...release/1.2.0

---------

Co-authored-by: jpirnay <jens@pirnay.com>
Co-authored-by: Dani Poveda <daniphii@outlook.com>
Co-authored-by: Baris Albayrak <80099286+barbarhan@users.noreply.github.com>
Co-authored-by: Barış Albayrak <barisa@pop-os.lan>
Co-authored-by: Stefan Blixten Karlsson <sbkarlsson@gmail.com>
Co-authored-by: Àngel <153315454+angeldenom@users.noreply.github.com>
Co-authored-by: Jonasz Potoniec <jonasz@potoniec.eu>
Co-authored-by: Егор Мартынов <martynovegorOF@yandex.ru>
Co-authored-by: Mirus <mirusim@gmail.com>
Co-authored-by: Spigaw <73850535+Spigaw@users.noreply.github.com>
Co-authored-by: ariel-lindemann <41641978+ariel-lindemann@users.noreply.github.com>
Co-authored-by: Nima Salami <54304457+hajisan@users.noreply.github.com>
Co-authored-by: Arthur Tazhitdinov <lisnake@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Bas van der Ploeg <bas@basvanderploeg.nl>
Co-authored-by: martin brook <martin.brook100@googlemail.com>
lukestein pushed a commit to lukestein/crosspoint-reader that referenced this pull request Apr 7, 2026
## Summary

It's been a little while since the last release, but the community has
been incredibly busy. With 155 changes from 48 contributors (30 of which
were new!), there was a lot to cover. Here are some of the highlights:

**🔤 Kerning, Ligatures, and Font Improvements**
Text rendering gets a significant upgrade with proper kerning and
ligature support, fixed-point fractional x-advance for more accurate
character placement, and font compression improvements that reduce flash
usage.

**📝 Footnotes**
Footnote anchor navigation lets you select a footnote reference and jump
to the footnote text, then jump back. Slim footnotes support is also
available for books that use inline footnotes.

**📖 EPUB Optimizer**
A new integrated EPUB optimizer can clean up and reprocess books for
better compatibility with the reader, directly from the device.

**🔋 Battery Charging Indicator**
You can now see when your device is actively charging, with a visual
indicator on the battery icon.

**💾 Crash Diagnostics**
When something goes wrong, the firmware now dumps a crash report to the
SD card — even without USB plugged in. This makes it much easier to
report and diagnose issues.

**🌐 New Languages**
The community continues to expand language support. New in this release:
Turkish, Danish, Finnish, Polish, Dutch, Belarusian, Italian, Ukrainian,
Romanian, Catalan, Vietnamese, and Kazakh — along with significant
improvements to existing translations.

**📂 File Management**
Multi-select file deletion, BMP image viewer in the file browser, hidden
directory browsing, and long-click file deletion from the file browser.

**⚡ Performance**
Under the hood, text layout switched from `std::list` to `std::vector`,
HTML entity lookups are now O(log(n)), font rendering is faster, image
decode is 5-20% faster with per-pixel overhead eliminated, and multiple
string allocation hot paths were eliminated. Pre-indexing of the next
chapter also reduces page-turn latency at chapter boundaries.

---

Along with all of the above, there are many other additions including
**WebDAV support**, **auto page turn**, **QR code for current page**,
**split status bar settings**, **screenshot capture**, **JSON-based
settings migration**, **light/dark theme groundwork**, and a long list
of stability fixes and translation improvements.

## What's Changed
### Features
* feat: Support for kerning and ligatures by @znelson in
crosspoint-reader#873
* feat: footnote anchor navigation by @Uri-Tauber in
crosspoint-reader#1245
* feat: slim footnotes support by @Uri-Tauber in
crosspoint-reader#1031
* feat: integrated epub optimizer by @zgredex and @pablohc in
crosspoint-reader#1224
* feat: battery charging indicator (mirroring PR crosspoint-reader#537) by @jpirnay in
crosspoint-reader#1427
* feat: dump crash report to sdcard by @ngxson in
crosspoint-reader#1145
* feat: Implement silent pre-indexing for the next chapter in
EpubReaderActivity by @LSTAR1900 in
crosspoint-reader#979
* feat: upgrade platform and support webdav by @dexif in
crosspoint-reader#1047
* feat: Auto Page Turn for Epub Reader by @GenesiaW in
crosspoint-reader#1219
* feat: enhance file deletion functionality with multi-select by
@Jessica765 in
crosspoint-reader#682
* feat: Long Click for File Deletion through File Browser by @Levrk in
crosspoint-reader#909
* feat: Take screenshots by @el in
crosspoint-reader#759
* feat: Current page as QR by @el in
crosspoint-reader#1099
* feat: Download links for web server by @el in
crosspoint-reader#1039
* feat: Added BmpViewer activity for viewing .bmp images in file browser
by @Levrk in
crosspoint-reader#887
* feat: User setting for image display by @jpirnay in
crosspoint-reader#1291
* feat: Show hidden directories in browser by @jpirnay in
crosspoint-reader#1288
* feat: Prefer ".sleep" over "sleep" for custom image directory by
@jpirnay in
crosspoint-reader#948
* feat: Allow a local configuration file for custom compiles by @jpirnay
in crosspoint-reader#879
* feat: Migrate binary settings to json by @jpirnay in
crosspoint-reader#920
* feat: split status bar setting by @whyte-j in
crosspoint-reader#733
* feat: wrapped text in GfxRender, implemented in themes so far by
@iandchasse in
crosspoint-reader#1141
* feat: Themed language screen by @CaptainFrito in
crosspoint-reader#1020
* feat: set WiFi hostname to CrossPoint-Reader-XXXXXXXXXXXX by @dexif in
crosspoint-reader#1107
* feat: Add maxAlloc to memory information by @jpirnay in
crosspoint-reader#1152
* feat: replace picojpeg with JPEGDEC for JPEG image decoding by
@martinbrook in
crosspoint-reader#1136
* feat: Add git branch to version information on settings screen by
@jpirnay in
crosspoint-reader#1225
* feat: sort languages in selection menu by @ariel-lindemann in
crosspoint-reader#1071
* feat: Latin Extended-B European glyphs by @znelson in
crosspoint-reader#1157
* feat: Latin Extended-B European glyphs by @znelson in
crosspoint-reader#1167
* feat: Vietnamese glyphs support by @danoooob in
crosspoint-reader#1147
* feat: add Turkish translation by @barbarhan in
crosspoint-reader#1192
* feat: add full Danish translation by @hajisan in
crosspoint-reader#1146
* feat: Add Finnish translations by @plahteenlahti in
crosspoint-reader#1133
* feat: Add Polish Language by @th0m4sek in
crosspoint-reader#1155
* feat: add Dutch translation by @basvdploeg in
crosspoint-reader#1204
* feat: add Belarusian translation by @dexif in
crosspoint-reader#1120
* feat: Add full Italian translations by @andreaturchet in
crosspoint-reader#1144
* feat: add Ukrainian translation by @mirus-ua in
crosspoint-reader#1065
* feat: Add Kazakh (kk) language support by @fsocietyipa in
crosspoint-reader#1377
* feat: added Romanian strings by @ariel-lindemann in
crosspoint-reader#987
* feat: add Catalan strings by @angeldenom in
crosspoint-reader#1049
* feat: Make directories stand out more in local file browser: "[dir]"
instead of "dir" by @jpirnay in
crosspoint-reader#1339
* feat: Add Polish strings for commits crosspoint-reader#1219,crosspoint-reader#1169,crosspoint-reader#1031 +tweaks by
@th0m4sek in
crosspoint-reader#1227
* feat: Polish translation tweaks by @th0m4sek in
crosspoint-reader#1193
### Fixes
* fix: Fix img layout issue / support CSS display:none for elements and
images by @jpirnay in
crosspoint-reader#1443
* fix: Overlapping battery percentage on image pages with anti-aliasing
by @znelson in
crosspoint-reader#1452
* fix: Fix prewarm perf when a page contains many styles by
@adriancaruana in
crosspoint-reader#1451
* fix: use sleep routine from the original firmware by @ngxson in
crosspoint-reader#1298
* fix: Prevent line breaks on common English contractions by @znelson in
crosspoint-reader#1405
* fix: Build with -fno-exceptions by @znelson in
crosspoint-reader#1412
* fix: Reduce flash usage by cleaning up I18n translations by @steka in
crosspoint-reader#1401
* fix: jpeg resource cleanup by @jpirnay in
crosspoint-reader#1320
* fix: back button in settings returns to tab bar first by @Cache8063 in
crosspoint-reader#1354
* fix: Init lastSleepImage (edge case) by @jpirnay in
crosspoint-reader#1360
* fix: Add special handling for apostrophe hyphenation by @jpirnay in
crosspoint-reader#1318
* fix: Fix inter-word spacing rounding error in text layout by @znelson
in crosspoint-reader#1311
* fix: load access fault crash by @Uri-Tauber in
crosspoint-reader#1370
* fix: Fix bootloop logging crash by @jpirnay in
crosspoint-reader#1357
* fix: dump crash log without usb plugged, bump release log to INFO by
@ngxson in
crosspoint-reader#1332
* fix: avoid zip filename overflow by @jpirnay in
crosspoint-reader#1321
* fix: Hanging indent (negative text-indent) and em-unit sizing by
@jpirnay in
crosspoint-reader#1229
* fix: Use fixed-point fractional x-advance and kerning for better text
layout by @znelson in
crosspoint-reader#1168
* fix: use HTTPClient::writeToStream for downloading files from OPDS by
@osteotek in
crosspoint-reader#1207
* fix: make file system operations thread-safe (HalFile) by @ngxson in
crosspoint-reader#1212
* fix: properly implement requestUpdateAndWait() by @ngxson in
crosspoint-reader#1218
* fix: prevent infinite render loop in Calibre Wireless after file
transfer by @pablohc in
crosspoint-reader#1070
* fix: WiFi lifecycle and hyphenation heap defragmentation for KOReader
sync by @jpirnay in
crosspoint-reader#1151
* fix: Fix coverRendered flag by @jpirnay in
crosspoint-reader#1154
* fix: Handle non-ASCII characters in sanitizeFilename by @znelson in
crosspoint-reader#1132
* fix: Update activity was missing "Back" button label by @znelson in
crosspoint-reader#1128
* fix: force auto-hinting for Bookerly to fix inconsistent stem widths
by @adriancaruana in
crosspoint-reader#1098
* fix: image centering bleed by @martinbrook in
crosspoint-reader#1096
* fix: double free WebDAVHandler by @ngxson in
crosspoint-reader#1093
* fix: Consider extra quotation styles when hyphenating quoted words by
@cbix in
crosspoint-reader#1077
* fix: acquire power lock before sleeping by @ngxson in
crosspoint-reader#1125
* fix: Unify inconsistent Wi-Fi/WiFi in Czech translation by @pepastach
in crosspoint-reader#1138
* fix: sdfat warning about redefinition of macro by @ngxson in
crosspoint-reader#1135
* fix: Close leaked file descriptors in SleepActivity and web server by
@brbla in
crosspoint-reader#869
* fix: Enable DESTRUCTOR_CLOSES_FILE flag by @daveallie in
crosspoint-reader#1075
* fix: Change "UI Font Size" to "Reader Font Size" by @divinitycove in
crosspoint-reader#1171
* fix: Hide unusable button hints when viewing empty directory by @Levrk
in crosspoint-reader#1253
* fix: broken translations in status bar settings by @ariel-lindemann in
crosspoint-reader#1188
* fix: clarity issue with ambiguous string `SET` by @ariel-lindemann in
crosspoint-reader#1169
* fix: Crash (Load access fault) when indexing chapters containing
characters unsupported by bold/italic font variants by @Uri-Tauber in
crosspoint-reader#997
* fix: Increase PNGdec buffer size to support wide images by @osteotek
in crosspoint-reader#995
* fix: Use HalPowerManager for battery percentage by @vjapolitzer in
crosspoint-reader#1005
* fix: Fix dangling pointer by @Uri-Tauber in
crosspoint-reader#1010
* fix: re-implementing Cover Outlines for the new Lyra Themes by @Levrk
in crosspoint-reader#1017
* fix: use double FAST_REFRESH to prevent washout on large grey images
by @martinbrook in
crosspoint-reader#957
* fix: Fixed Image Sizing When No Width is Set by @DestinySpeaker in
crosspoint-reader#1002
* fix: Strip unused CSS rules by @daveallie in
crosspoint-reader#1014
* fix: continue reading card classic theme by @pablohc in
crosspoint-reader#990
* fix: Destroy CSS Cache file when invalid by @daveallie in
crosspoint-reader#1018
* fix: Shorten "Forget Wifi" button labels to fit on button by
@lukestein in
crosspoint-reader#1045
* fix: improve Spanish translations by @pablohc in
crosspoint-reader#1054
* fix: Fixed book title in home screen by @DestinySpeaker in
crosspoint-reader#1013
* fix: Fix hyphenation and rendering of decomposed characters by
@jpirnay in
crosspoint-reader#1037
* fix: Improve and add Spanish translations by @DaniPhii in
crosspoint-reader#1338
* fix: improve and add Spanish translations by @DaniPhii in
crosspoint-reader#1254
* fix: improve and add Swedish translations by @steka in
crosspoint-reader#1317
* fix: Extend missing / amend existing German translations by @jpirnay
in crosspoint-reader#1226
* fix: update french.yaml file to have a better French translation of
the CFW by @Spigaw in
crosspoint-reader#1130
* fix: added romanian translation to new strings by @ariel-lindemann in
crosspoint-reader#1105
* fix: add missing romanian strings by @ariel-lindemann in
crosspoint-reader#1187
* fix: add new Ukrainian translation line for STR_SCREENSHOT_BUTTON by
@mirus-ua in
crosspoint-reader#1149
* fix: Dutch translation prefix correction by @basvdploeg in
crosspoint-reader#1223
* fix: Small typo in i18n.md regarding C++ identifiers by
@victordomingos in
crosspoint-reader#1210
* fix: typo in USER_GUIDE.md by @arnaugamez in
crosspoint-reader#1036
* fix: add missing keyboard metrics to Lyra3CoversTheme by @dexif in
crosspoint-reader#1101

### Internal
* perf: font-compression improvements by @adriancaruana in
crosspoint-reader#1056
* perf: Improve font drawing performance by @jpirnay in
crosspoint-reader#978
* perf: Replace std::list with std::vector in text layout by @znelson in
crosspoint-reader#1038
* perf: Optimize HTML entities lookup to O(log(n)) by @Uri-Tauber in
crosspoint-reader#1194
* perf: UITheme::getMetrics const and const-ref usage by @znelson in
crosspoint-reader#1094
* perf: Avoid creating strings for file extension checks by @znelson in
crosspoint-reader#1303
* perf: Eliminate per-pixel overheads in image rendering by @martinbrook
in crosspoint-reader#1293
* perf: Update github actions for optimal performance with pioarduino by
@Jason2866 in
crosspoint-reader#1080
* style: Phase 1 - Simple light dark themes by @cdmoro in
crosspoint-reader#1006
* refactor: implement ActivityManager by @ngxson in
crosspoint-reader#1016
* refactor: Simplify REPLACEMENT_GLYPH fallback by @znelson in
crosspoint-reader#1119
* refactor: Simplify new setting introduction by @jpirnay in
crosspoint-reader#1086
* refactor: Use std binary search algorithms for font lookups by
@znelson in
crosspoint-reader#1202
* refactor: rename MyLibrary to FileBrowser by @osteotek in
crosspoint-reader#1260
* refactor: Avoid rebuilding cache path strings by @znelson in
crosspoint-reader#1300
* refactor: reader utils by @Uri-Tauber in
crosspoint-reader#1329
* chore: Remove miniz and modularise inflation logic by @daveallie in
crosspoint-reader#1073
* chore: Resolve several build warnings by @daveallie in
crosspoint-reader#1076
* chore: Removed generated language headers by @znelson in
crosspoint-reader#1156
* chore: Added generated lang headers to .gitignore by @znelson in
crosspoint-reader#1158
* chore: remove redundant xTaskCreate by @ngxson in
crosspoint-reader#1264
* chore: Removed unused PlatformIO include directory placeholder by
@znelson in
crosspoint-reader#1417
* chore: micro-optimisation: early exit on fillUncompressedSizes by
@jpirnay in
crosspoint-reader#1322
* chore: change label while on settings tab actions by @jpirnay in
crosspoint-reader#1325
* chore: add firmware size history script by @znelson in
crosspoint-reader#1235
* chore: Add powershell script for clang-formatting by @jpirnay in
crosspoint-reader#1472
* chore: Removed unused ConfirmationActivity member by @znelson in
crosspoint-reader#1234
* chore: Update russian.yaml by @madebyKir in
crosspoint-reader#1198
* chore: new Ukrainian translation lines by @mirus-ua in
crosspoint-reader#1199
* chore: new Ukrainian localization strings by @mirus-ua in
crosspoint-reader#1270
* chore: Polish localization for STR_DELETE by @JonaszPotoniec in
crosspoint-reader#1323
* chore: Image settings Polish localization by @znelson in
crosspoint-reader#1299
* chore: add missing Catalan strings by @angeldenom in
crosspoint-reader#1302
* chore: add missing translations for Romanian by @ariel-lindemann in
crosspoint-reader#1265
* chore: Add Portuguese (Portugal) translator to the list by
@victordomingos in
crosspoint-reader#1211
* chore: Reduce flash usage by cleaning up I18n translations by @steka
in crosspoint-reader#1401
* docs: Add lightweight contributor onboarding documentation by @bilalix
in crosspoint-reader#894
* docs: ActivityManager migration guide by @znelson in
crosspoint-reader#1222
* docs: USER_GUIDE.md update for 1.1.0 by @divinitycove in
crosspoint-reader#1108
* docs: add quick KOReader sync setup guide by @wjhrdy in
crosspoint-reader#1181
* docs: image support marked as completed by @ariel-lindemann in
crosspoint-reader#1008
* feat: aiagent context definition by @jpirnay in
crosspoint-reader#922
* chore: Update SKILL.md to reflect generated i18n files are gitignored
by @znelson in
crosspoint-reader#1423
* fix: ActivityManager tweaks by @znelson in
crosspoint-reader#1220
* fix: Correct relative file paths in SKILL.md documentation by @pablohc
in crosspoint-reader#1304
* fix: add Technically Unsupported section to SCOPE.md by @Uri-Tauber in
crosspoint-reader#1295

## New Contributors
* @DestinySpeaker made their first contribution in
crosspoint-reader#1002
* @arnaugamez made their first contribution in
crosspoint-reader#1036
* @angeldenom made their first contribution in
crosspoint-reader#1049
* @cdmoro made their first contribution in
crosspoint-reader#1006
* @bilalix made their first contribution in
crosspoint-reader#894
* @Jessica765 made their first contribution in
crosspoint-reader#682
* @brbla made their first contribution in
crosspoint-reader#869
* @dexif made their first contribution in
crosspoint-reader#1047
* @mirus-ua made their first contribution in
crosspoint-reader#1065
* @cbix made their first contribution in
crosspoint-reader#1077
* @divinitycove made their first contribution in
crosspoint-reader#1108
* @pepastach made their first contribution in
crosspoint-reader#1138
* @Jason2866 made their first contribution in
crosspoint-reader#1080
* @andreaturchet made their first contribution in
crosspoint-reader#1144
* @Spigaw made their first contribution in
crosspoint-reader#1130
* @iandchasse made their first contribution in
crosspoint-reader#1141
* @th0m4sek made their first contribution in
crosspoint-reader#1155
* @plahteenlahti made their first contribution in
crosspoint-reader#1133
* @hajisan made their first contribution in
crosspoint-reader#1146
* @madebyKir made their first contribution in
crosspoint-reader#1198
* @victordomingos made their first contribution in
crosspoint-reader#1210
* @basvdploeg made their first contribution in
crosspoint-reader#1204
* @wjhrdy made their first contribution in
crosspoint-reader#1181
* @DaniPhii made their first contribution in
crosspoint-reader#1254
* @steka made their first contribution in
crosspoint-reader#1317
* @barbarhan made their first contribution in
crosspoint-reader#1192
* @JonaszPotoniec made their first contribution in
crosspoint-reader#1323
* @Cache8063 made their first contribution in
crosspoint-reader#1354
* @fsocietyipa made their first contribution in
crosspoint-reader#1377
* @LSTAR1900 made their first contribution in
crosspoint-reader#979
* @zgredex made their first contribution in
crosspoint-reader#1224

**Full Changelog**:
crosspoint-reader/crosspoint-reader@1.1.1...release/1.2.0

---------

Co-authored-by: jpirnay <jens@pirnay.com>
Co-authored-by: Dani Poveda <daniphii@outlook.com>
Co-authored-by: Baris Albayrak <80099286+barbarhan@users.noreply.github.com>
Co-authored-by: Barış Albayrak <barisa@pop-os.lan>
Co-authored-by: Stefan Blixten Karlsson <sbkarlsson@gmail.com>
Co-authored-by: Àngel <153315454+angeldenom@users.noreply.github.com>
Co-authored-by: Jonasz Potoniec <jonasz@potoniec.eu>
Co-authored-by: Егор Мартынов <martynovegorOF@yandex.ru>
Co-authored-by: Mirus <mirusim@gmail.com>
Co-authored-by: Spigaw <73850535+Spigaw@users.noreply.github.com>
Co-authored-by: ariel-lindemann <41641978+ariel-lindemann@users.noreply.github.com>
Co-authored-by: Nima Salami <54304457+hajisan@users.noreply.github.com>
Co-authored-by: Arthur Tazhitdinov <lisnake@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Bas van der Ploeg <bas@basvanderploeg.nl>
Co-authored-by: martin brook <martin.brook100@googlemail.com>
bdeshi pushed a commit to bdeshi/crosspoint-reader that referenced this pull request Apr 8, 2026
## Summary

It's been a little while since the last release, but the community has
been incredibly busy. With 155 changes from 48 contributors (30 of which
were new!), there was a lot to cover. Here are some of the highlights:

**🔤 Kerning, Ligatures, and Font Improvements**
Text rendering gets a significant upgrade with proper kerning and
ligature support, fixed-point fractional x-advance for more accurate
character placement, and font compression improvements that reduce flash
usage.

**📝 Footnotes**
Footnote anchor navigation lets you select a footnote reference and jump
to the footnote text, then jump back. Slim footnotes support is also
available for books that use inline footnotes.

**📖 EPUB Optimizer**
A new integrated EPUB optimizer can clean up and reprocess books for
better compatibility with the reader, directly from the device.

**🔋 Battery Charging Indicator**
You can now see when your device is actively charging, with a visual
indicator on the battery icon.

**💾 Crash Diagnostics**
When something goes wrong, the firmware now dumps a crash report to the
SD card — even without USB plugged in. This makes it much easier to
report and diagnose issues.

**🌐 New Languages**
The community continues to expand language support. New in this release:
Turkish, Danish, Finnish, Polish, Dutch, Belarusian, Italian, Ukrainian,
Romanian, Catalan, Vietnamese, and Kazakh — along with significant
improvements to existing translations.

**📂 File Management**
Multi-select file deletion, BMP image viewer in the file browser, hidden
directory browsing, and long-click file deletion from the file browser.

**⚡ Performance**
Under the hood, text layout switched from `std::list` to `std::vector`,
HTML entity lookups are now O(log(n)), font rendering is faster, image
decode is 5-20% faster with per-pixel overhead eliminated, and multiple
string allocation hot paths were eliminated. Pre-indexing of the next
chapter also reduces page-turn latency at chapter boundaries.

---

Along with all of the above, there are many other additions including
**WebDAV support**, **auto page turn**, **QR code for current page**,
**split status bar settings**, **screenshot capture**, **JSON-based
settings migration**, **light/dark theme groundwork**, and a long list
of stability fixes and translation improvements.

## What's Changed
### Features
* feat: Support for kerning and ligatures by @znelson in
crosspoint-reader#873
* feat: footnote anchor navigation by @Uri-Tauber in
crosspoint-reader#1245
* feat: slim footnotes support by @Uri-Tauber in
crosspoint-reader#1031
* feat: integrated epub optimizer by @zgredex and @pablohc in
crosspoint-reader#1224
* feat: battery charging indicator (mirroring PR crosspoint-reader#537) by @jpirnay in
crosspoint-reader#1427
* feat: dump crash report to sdcard by @ngxson in
crosspoint-reader#1145
* feat: Implement silent pre-indexing for the next chapter in
EpubReaderActivity by @LSTAR1900 in
crosspoint-reader#979
* feat: upgrade platform and support webdav by @dexif in
crosspoint-reader#1047
* feat: Auto Page Turn for Epub Reader by @GenesiaW in
crosspoint-reader#1219
* feat: enhance file deletion functionality with multi-select by
@Jessica765 in
crosspoint-reader#682
* feat: Long Click for File Deletion through File Browser by @Levrk in
crosspoint-reader#909
* feat: Take screenshots by @el in
crosspoint-reader#759
* feat: Current page as QR by @el in
crosspoint-reader#1099
* feat: Download links for web server by @el in
crosspoint-reader#1039
* feat: Added BmpViewer activity for viewing .bmp images in file browser
by @Levrk in
crosspoint-reader#887
* feat: User setting for image display by @jpirnay in
crosspoint-reader#1291
* feat: Show hidden directories in browser by @jpirnay in
crosspoint-reader#1288
* feat: Prefer ".sleep" over "sleep" for custom image directory by
@jpirnay in
crosspoint-reader#948
* feat: Allow a local configuration file for custom compiles by @jpirnay
in crosspoint-reader#879
* feat: Migrate binary settings to json by @jpirnay in
crosspoint-reader#920
* feat: split status bar setting by @whyte-j in
crosspoint-reader#733
* feat: wrapped text in GfxRender, implemented in themes so far by
@iandchasse in
crosspoint-reader#1141
* feat: Themed language screen by @CaptainFrito in
crosspoint-reader#1020
* feat: set WiFi hostname to CrossPoint-Reader-XXXXXXXXXXXX by @dexif in
crosspoint-reader#1107
* feat: Add maxAlloc to memory information by @jpirnay in
crosspoint-reader#1152
* feat: replace picojpeg with JPEGDEC for JPEG image decoding by
@martinbrook in
crosspoint-reader#1136
* feat: Add git branch to version information on settings screen by
@jpirnay in
crosspoint-reader#1225
* feat: sort languages in selection menu by @ariel-lindemann in
crosspoint-reader#1071
* feat: Latin Extended-B European glyphs by @znelson in
crosspoint-reader#1157
* feat: Latin Extended-B European glyphs by @znelson in
crosspoint-reader#1167
* feat: Vietnamese glyphs support by @danoooob in
crosspoint-reader#1147
* feat: add Turkish translation by @barbarhan in
crosspoint-reader#1192
* feat: add full Danish translation by @hajisan in
crosspoint-reader#1146
* feat: Add Finnish translations by @plahteenlahti in
crosspoint-reader#1133
* feat: Add Polish Language by @th0m4sek in
crosspoint-reader#1155
* feat: add Dutch translation by @basvdploeg in
crosspoint-reader#1204
* feat: add Belarusian translation by @dexif in
crosspoint-reader#1120
* feat: Add full Italian translations by @andreaturchet in
crosspoint-reader#1144
* feat: add Ukrainian translation by @mirus-ua in
crosspoint-reader#1065
* feat: Add Kazakh (kk) language support by @fsocietyipa in
crosspoint-reader#1377
* feat: added Romanian strings by @ariel-lindemann in
crosspoint-reader#987
* feat: add Catalan strings by @angeldenom in
crosspoint-reader#1049
* feat: Make directories stand out more in local file browser: "[dir]"
instead of "dir" by @jpirnay in
crosspoint-reader#1339
* feat: Add Polish strings for commits crosspoint-reader#1219,crosspoint-reader#1169,crosspoint-reader#1031 +tweaks by
@th0m4sek in
crosspoint-reader#1227
* feat: Polish translation tweaks by @th0m4sek in
crosspoint-reader#1193
### Fixes
* fix: Fix img layout issue / support CSS display:none for elements and
images by @jpirnay in
crosspoint-reader#1443
* fix: Overlapping battery percentage on image pages with anti-aliasing
by @znelson in
crosspoint-reader#1452
* fix: Fix prewarm perf when a page contains many styles by
@adriancaruana in
crosspoint-reader#1451
* fix: use sleep routine from the original firmware by @ngxson in
crosspoint-reader#1298
* fix: Prevent line breaks on common English contractions by @znelson in
crosspoint-reader#1405
* fix: Build with -fno-exceptions by @znelson in
crosspoint-reader#1412
* fix: Reduce flash usage by cleaning up I18n translations by @steka in
crosspoint-reader#1401
* fix: jpeg resource cleanup by @jpirnay in
crosspoint-reader#1320
* fix: back button in settings returns to tab bar first by @Cache8063 in
crosspoint-reader#1354
* fix: Init lastSleepImage (edge case) by @jpirnay in
crosspoint-reader#1360
* fix: Add special handling for apostrophe hyphenation by @jpirnay in
crosspoint-reader#1318
* fix: Fix inter-word spacing rounding error in text layout by @znelson
in crosspoint-reader#1311
* fix: load access fault crash by @Uri-Tauber in
crosspoint-reader#1370
* fix: Fix bootloop logging crash by @jpirnay in
crosspoint-reader#1357
* fix: dump crash log without usb plugged, bump release log to INFO by
@ngxson in
crosspoint-reader#1332
* fix: avoid zip filename overflow by @jpirnay in
crosspoint-reader#1321
* fix: Hanging indent (negative text-indent) and em-unit sizing by
@jpirnay in
crosspoint-reader#1229
* fix: Use fixed-point fractional x-advance and kerning for better text
layout by @znelson in
crosspoint-reader#1168
* fix: use HTTPClient::writeToStream for downloading files from OPDS by
@osteotek in
crosspoint-reader#1207
* fix: make file system operations thread-safe (HalFile) by @ngxson in
crosspoint-reader#1212
* fix: properly implement requestUpdateAndWait() by @ngxson in
crosspoint-reader#1218
* fix: prevent infinite render loop in Calibre Wireless after file
transfer by @pablohc in
crosspoint-reader#1070
* fix: WiFi lifecycle and hyphenation heap defragmentation for KOReader
sync by @jpirnay in
crosspoint-reader#1151
* fix: Fix coverRendered flag by @jpirnay in
crosspoint-reader#1154
* fix: Handle non-ASCII characters in sanitizeFilename by @znelson in
crosspoint-reader#1132
* fix: Update activity was missing "Back" button label by @znelson in
crosspoint-reader#1128
* fix: force auto-hinting for Bookerly to fix inconsistent stem widths
by @adriancaruana in
crosspoint-reader#1098
* fix: image centering bleed by @martinbrook in
crosspoint-reader#1096
* fix: double free WebDAVHandler by @ngxson in
crosspoint-reader#1093
* fix: Consider extra quotation styles when hyphenating quoted words by
@cbix in
crosspoint-reader#1077
* fix: acquire power lock before sleeping by @ngxson in
crosspoint-reader#1125
* fix: Unify inconsistent Wi-Fi/WiFi in Czech translation by @pepastach
in crosspoint-reader#1138
* fix: sdfat warning about redefinition of macro by @ngxson in
crosspoint-reader#1135
* fix: Close leaked file descriptors in SleepActivity and web server by
@brbla in
crosspoint-reader#869
* fix: Enable DESTRUCTOR_CLOSES_FILE flag by @daveallie in
crosspoint-reader#1075
* fix: Change "UI Font Size" to "Reader Font Size" by @divinitycove in
crosspoint-reader#1171
* fix: Hide unusable button hints when viewing empty directory by @Levrk
in crosspoint-reader#1253
* fix: broken translations in status bar settings by @ariel-lindemann in
crosspoint-reader#1188
* fix: clarity issue with ambiguous string `SET` by @ariel-lindemann in
crosspoint-reader#1169
* fix: Crash (Load access fault) when indexing chapters containing
characters unsupported by bold/italic font variants by @Uri-Tauber in
crosspoint-reader#997
* fix: Increase PNGdec buffer size to support wide images by @osteotek
in crosspoint-reader#995
* fix: Use HalPowerManager for battery percentage by @vjapolitzer in
crosspoint-reader#1005
* fix: Fix dangling pointer by @Uri-Tauber in
crosspoint-reader#1010
* fix: re-implementing Cover Outlines for the new Lyra Themes by @Levrk
in crosspoint-reader#1017
* fix: use double FAST_REFRESH to prevent washout on large grey images
by @martinbrook in
crosspoint-reader#957
* fix: Fixed Image Sizing When No Width is Set by @DestinySpeaker in
crosspoint-reader#1002
* fix: Strip unused CSS rules by @daveallie in
crosspoint-reader#1014
* fix: continue reading card classic theme by @pablohc in
crosspoint-reader#990
* fix: Destroy CSS Cache file when invalid by @daveallie in
crosspoint-reader#1018
* fix: Shorten "Forget Wifi" button labels to fit on button by
@lukestein in
crosspoint-reader#1045
* fix: improve Spanish translations by @pablohc in
crosspoint-reader#1054
* fix: Fixed book title in home screen by @DestinySpeaker in
crosspoint-reader#1013
* fix: Fix hyphenation and rendering of decomposed characters by
@jpirnay in
crosspoint-reader#1037
* fix: Improve and add Spanish translations by @DaniPhii in
crosspoint-reader#1338
* fix: improve and add Spanish translations by @DaniPhii in
crosspoint-reader#1254
* fix: improve and add Swedish translations by @steka in
crosspoint-reader#1317
* fix: Extend missing / amend existing German translations by @jpirnay
in crosspoint-reader#1226
* fix: update french.yaml file to have a better French translation of
the CFW by @Spigaw in
crosspoint-reader#1130
* fix: added romanian translation to new strings by @ariel-lindemann in
crosspoint-reader#1105
* fix: add missing romanian strings by @ariel-lindemann in
crosspoint-reader#1187
* fix: add new Ukrainian translation line for STR_SCREENSHOT_BUTTON by
@mirus-ua in
crosspoint-reader#1149
* fix: Dutch translation prefix correction by @basvdploeg in
crosspoint-reader#1223
* fix: Small typo in i18n.md regarding C++ identifiers by
@victordomingos in
crosspoint-reader#1210
* fix: typo in USER_GUIDE.md by @arnaugamez in
crosspoint-reader#1036
* fix: add missing keyboard metrics to Lyra3CoversTheme by @dexif in
crosspoint-reader#1101

### Internal
* perf: font-compression improvements by @adriancaruana in
crosspoint-reader#1056
* perf: Improve font drawing performance by @jpirnay in
crosspoint-reader#978
* perf: Replace std::list with std::vector in text layout by @znelson in
crosspoint-reader#1038
* perf: Optimize HTML entities lookup to O(log(n)) by @Uri-Tauber in
crosspoint-reader#1194
* perf: UITheme::getMetrics const and const-ref usage by @znelson in
crosspoint-reader#1094
* perf: Avoid creating strings for file extension checks by @znelson in
crosspoint-reader#1303
* perf: Eliminate per-pixel overheads in image rendering by @martinbrook
in crosspoint-reader#1293
* perf: Update github actions for optimal performance with pioarduino by
@Jason2866 in
crosspoint-reader#1080
* style: Phase 1 - Simple light dark themes by @cdmoro in
crosspoint-reader#1006
* refactor: implement ActivityManager by @ngxson in
crosspoint-reader#1016
* refactor: Simplify REPLACEMENT_GLYPH fallback by @znelson in
crosspoint-reader#1119
* refactor: Simplify new setting introduction by @jpirnay in
crosspoint-reader#1086
* refactor: Use std binary search algorithms for font lookups by
@znelson in
crosspoint-reader#1202
* refactor: rename MyLibrary to FileBrowser by @osteotek in
crosspoint-reader#1260
* refactor: Avoid rebuilding cache path strings by @znelson in
crosspoint-reader#1300
* refactor: reader utils by @Uri-Tauber in
crosspoint-reader#1329
* chore: Remove miniz and modularise inflation logic by @daveallie in
crosspoint-reader#1073
* chore: Resolve several build warnings by @daveallie in
crosspoint-reader#1076
* chore: Removed generated language headers by @znelson in
crosspoint-reader#1156
* chore: Added generated lang headers to .gitignore by @znelson in
crosspoint-reader#1158
* chore: remove redundant xTaskCreate by @ngxson in
crosspoint-reader#1264
* chore: Removed unused PlatformIO include directory placeholder by
@znelson in
crosspoint-reader#1417
* chore: micro-optimisation: early exit on fillUncompressedSizes by
@jpirnay in
crosspoint-reader#1322
* chore: change label while on settings tab actions by @jpirnay in
crosspoint-reader#1325
* chore: add firmware size history script by @znelson in
crosspoint-reader#1235
* chore: Add powershell script for clang-formatting by @jpirnay in
crosspoint-reader#1472
* chore: Removed unused ConfirmationActivity member by @znelson in
crosspoint-reader#1234
* chore: Update russian.yaml by @madebyKir in
crosspoint-reader#1198
* chore: new Ukrainian translation lines by @mirus-ua in
crosspoint-reader#1199
* chore: new Ukrainian localization strings by @mirus-ua in
crosspoint-reader#1270
* chore: Polish localization for STR_DELETE by @JonaszPotoniec in
crosspoint-reader#1323
* chore: Image settings Polish localization by @znelson in
crosspoint-reader#1299
* chore: add missing Catalan strings by @angeldenom in
crosspoint-reader#1302
* chore: add missing translations for Romanian by @ariel-lindemann in
crosspoint-reader#1265
* chore: Add Portuguese (Portugal) translator to the list by
@victordomingos in
crosspoint-reader#1211
* chore: Reduce flash usage by cleaning up I18n translations by @steka
in crosspoint-reader#1401
* docs: Add lightweight contributor onboarding documentation by @bilalix
in crosspoint-reader#894
* docs: ActivityManager migration guide by @znelson in
crosspoint-reader#1222
* docs: USER_GUIDE.md update for 1.1.0 by @divinitycove in
crosspoint-reader#1108
* docs: add quick KOReader sync setup guide by @wjhrdy in
crosspoint-reader#1181
* docs: image support marked as completed by @ariel-lindemann in
crosspoint-reader#1008
* feat: aiagent context definition by @jpirnay in
crosspoint-reader#922
* chore: Update SKILL.md to reflect generated i18n files are gitignored
by @znelson in
crosspoint-reader#1423
* fix: ActivityManager tweaks by @znelson in
crosspoint-reader#1220
* fix: Correct relative file paths in SKILL.md documentation by @pablohc
in crosspoint-reader#1304
* fix: add Technically Unsupported section to SCOPE.md by @Uri-Tauber in
crosspoint-reader#1295

## New Contributors
* @DestinySpeaker made their first contribution in
crosspoint-reader#1002
* @arnaugamez made their first contribution in
crosspoint-reader#1036
* @angeldenom made their first contribution in
crosspoint-reader#1049
* @cdmoro made their first contribution in
crosspoint-reader#1006
* @bilalix made their first contribution in
crosspoint-reader#894
* @Jessica765 made their first contribution in
crosspoint-reader#682
* @brbla made their first contribution in
crosspoint-reader#869
* @dexif made their first contribution in
crosspoint-reader#1047
* @mirus-ua made their first contribution in
crosspoint-reader#1065
* @cbix made their first contribution in
crosspoint-reader#1077
* @divinitycove made their first contribution in
crosspoint-reader#1108
* @pepastach made their first contribution in
crosspoint-reader#1138
* @Jason2866 made their first contribution in
crosspoint-reader#1080
* @andreaturchet made their first contribution in
crosspoint-reader#1144
* @Spigaw made their first contribution in
crosspoint-reader#1130
* @iandchasse made their first contribution in
crosspoint-reader#1141
* @th0m4sek made their first contribution in
crosspoint-reader#1155
* @plahteenlahti made their first contribution in
crosspoint-reader#1133
* @hajisan made their first contribution in
crosspoint-reader#1146
* @madebyKir made their first contribution in
crosspoint-reader#1198
* @victordomingos made their first contribution in
crosspoint-reader#1210
* @basvdploeg made their first contribution in
crosspoint-reader#1204
* @wjhrdy made their first contribution in
crosspoint-reader#1181
* @DaniPhii made their first contribution in
crosspoint-reader#1254
* @steka made their first contribution in
crosspoint-reader#1317
* @barbarhan made their first contribution in
crosspoint-reader#1192
* @JonaszPotoniec made their first contribution in
crosspoint-reader#1323
* @Cache8063 made their first contribution in
crosspoint-reader#1354
* @fsocietyipa made their first contribution in
crosspoint-reader#1377
* @LSTAR1900 made their first contribution in
crosspoint-reader#979
* @zgredex made their first contribution in
crosspoint-reader#1224

**Full Changelog**:
crosspoint-reader/crosspoint-reader@1.1.1...release/1.2.0

---------

Co-authored-by: jpirnay <jens@pirnay.com>
Co-authored-by: Dani Poveda <daniphii@outlook.com>
Co-authored-by: Baris Albayrak <80099286+barbarhan@users.noreply.github.com>
Co-authored-by: Barış Albayrak <barisa@pop-os.lan>
Co-authored-by: Stefan Blixten Karlsson <sbkarlsson@gmail.com>
Co-authored-by: Àngel <153315454+angeldenom@users.noreply.github.com>
Co-authored-by: Jonasz Potoniec <jonasz@potoniec.eu>
Co-authored-by: Егор Мартынов <martynovegorOF@yandex.ru>
Co-authored-by: Mirus <mirusim@gmail.com>
Co-authored-by: Spigaw <73850535+Spigaw@users.noreply.github.com>
Co-authored-by: ariel-lindemann <41641978+ariel-lindemann@users.noreply.github.com>
Co-authored-by: Nima Salami <54304457+hajisan@users.noreply.github.com>
Co-authored-by: Arthur Tazhitdinov <lisnake@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Bas van der Ploeg <bas@basvanderploeg.nl>
Co-authored-by: martin brook <martin.brook100@googlemail.com>
aBER0724 pushed a commit to aBER0724/crosspoint-reader-cjk that referenced this pull request May 7, 2026
## Summary

It's been a little while since the last release, but the community has
been incredibly busy. With 155 changes from 48 contributors (30 of which
were new!), there was a lot to cover. Here are some of the highlights:

**🔤 Kerning, Ligatures, and Font Improvements**
Text rendering gets a significant upgrade with proper kerning and
ligature support, fixed-point fractional x-advance for more accurate
character placement, and font compression improvements that reduce flash
usage.

**📝 Footnotes**
Footnote anchor navigation lets you select a footnote reference and jump
to the footnote text, then jump back. Slim footnotes support is also
available for books that use inline footnotes.

**📖 EPUB Optimizer**
A new integrated EPUB optimizer can clean up and reprocess books for
better compatibility with the reader, directly from the device.

**🔋 Battery Charging Indicator**
You can now see when your device is actively charging, with a visual
indicator on the battery icon.

**💾 Crash Diagnostics**
When something goes wrong, the firmware now dumps a crash report to the
SD card — even without USB plugged in. This makes it much easier to
report and diagnose issues.

**🌐 New Languages**
The community continues to expand language support. New in this release:
Turkish, Danish, Finnish, Polish, Dutch, Belarusian, Italian, Ukrainian,
Romanian, Catalan, Vietnamese, and Kazakh — along with significant
improvements to existing translations.

**📂 File Management**
Multi-select file deletion, BMP image viewer in the file browser, hidden
directory browsing, and long-click file deletion from the file browser.

**⚡ Performance**
Under the hood, text layout switched from `std::list` to `std::vector`,
HTML entity lookups are now O(log(n)), font rendering is faster, image
decode is 5-20% faster with per-pixel overhead eliminated, and multiple
string allocation hot paths were eliminated. Pre-indexing of the next
chapter also reduces page-turn latency at chapter boundaries.

---

Along with all of the above, there are many other additions including
**WebDAV support**, **auto page turn**, **QR code for current page**,
**split status bar settings**, **screenshot capture**, **JSON-based
settings migration**, **light/dark theme groundwork**, and a long list
of stability fixes and translation improvements.

## What's Changed
### Features
* feat: Support for kerning and ligatures by @znelson in
crosspoint-reader#873
* feat: footnote anchor navigation by @Uri-Tauber in
crosspoint-reader#1245
* feat: slim footnotes support by @Uri-Tauber in
crosspoint-reader#1031
* feat: integrated epub optimizer by @zgredex and @pablohc in
crosspoint-reader#1224
* feat: battery charging indicator (mirroring PR crosspoint-reader#537) by @jpirnay in
crosspoint-reader#1427
* feat: dump crash report to sdcard by @ngxson in
crosspoint-reader#1145
* feat: Implement silent pre-indexing for the next chapter in
EpubReaderActivity by @LSTAR1900 in
crosspoint-reader#979
* feat: upgrade platform and support webdav by @dexif in
crosspoint-reader#1047
* feat: Auto Page Turn for Epub Reader by @GenesiaW in
crosspoint-reader#1219
* feat: enhance file deletion functionality with multi-select by
@Jessica765 in
crosspoint-reader#682
* feat: Long Click for File Deletion through File Browser by @Levrk in
crosspoint-reader#909
* feat: Take screenshots by @el in
crosspoint-reader#759
* feat: Current page as QR by @el in
crosspoint-reader#1099
* feat: Download links for web server by @el in
crosspoint-reader#1039
* feat: Added BmpViewer activity for viewing .bmp images in file browser
by @Levrk in
crosspoint-reader#887
* feat: User setting for image display by @jpirnay in
crosspoint-reader#1291
* feat: Show hidden directories in browser by @jpirnay in
crosspoint-reader#1288
* feat: Prefer ".sleep" over "sleep" for custom image directory by
@jpirnay in
crosspoint-reader#948
* feat: Allow a local configuration file for custom compiles by @jpirnay
in crosspoint-reader#879
* feat: Migrate binary settings to json by @jpirnay in
crosspoint-reader#920
* feat: split status bar setting by @whyte-j in
crosspoint-reader#733
* feat: wrapped text in GfxRender, implemented in themes so far by
@iandchasse in
crosspoint-reader#1141
* feat: Themed language screen by @CaptainFrito in
crosspoint-reader#1020
* feat: set WiFi hostname to CrossPoint-Reader-XXXXXXXXXXXX by @dexif in
crosspoint-reader#1107
* feat: Add maxAlloc to memory information by @jpirnay in
crosspoint-reader#1152
* feat: replace picojpeg with JPEGDEC for JPEG image decoding by
@martinbrook in
crosspoint-reader#1136
* feat: Add git branch to version information on settings screen by
@jpirnay in
crosspoint-reader#1225
* feat: sort languages in selection menu by @ariel-lindemann in
crosspoint-reader#1071
* feat: Latin Extended-B European glyphs by @znelson in
crosspoint-reader#1157
* feat: Latin Extended-B European glyphs by @znelson in
crosspoint-reader#1167
* feat: Vietnamese glyphs support by @danoooob in
crosspoint-reader#1147
* feat: add Turkish translation by @barbarhan in
crosspoint-reader#1192
* feat: add full Danish translation by @hajisan in
crosspoint-reader#1146
* feat: Add Finnish translations by @plahteenlahti in
crosspoint-reader#1133
* feat: Add Polish Language by @th0m4sek in
crosspoint-reader#1155
* feat: add Dutch translation by @basvdploeg in
crosspoint-reader#1204
* feat: add Belarusian translation by @dexif in
crosspoint-reader#1120
* feat: Add full Italian translations by @andreaturchet in
crosspoint-reader#1144
* feat: add Ukrainian translation by @mirus-ua in
crosspoint-reader#1065
* feat: Add Kazakh (kk) language support by @fsocietyipa in
crosspoint-reader#1377
* feat: added Romanian strings by @ariel-lindemann in
crosspoint-reader#987
* feat: add Catalan strings by @angeldenom in
crosspoint-reader#1049
* feat: Make directories stand out more in local file browser: "[dir]"
instead of "dir" by @jpirnay in
crosspoint-reader#1339
* feat: Add Polish strings for commits crosspoint-reader#1219,crosspoint-reader#1169,crosspoint-reader#1031 +tweaks by
@th0m4sek in
crosspoint-reader#1227
* feat: Polish translation tweaks by @th0m4sek in
crosspoint-reader#1193
### Fixes
* fix: Fix img layout issue / support CSS display:none for elements and
images by @jpirnay in
crosspoint-reader#1443
* fix: Overlapping battery percentage on image pages with anti-aliasing
by @znelson in
crosspoint-reader#1452
* fix: Fix prewarm perf when a page contains many styles by
@adriancaruana in
crosspoint-reader#1451
* fix: use sleep routine from the original firmware by @ngxson in
crosspoint-reader#1298
* fix: Prevent line breaks on common English contractions by @znelson in
crosspoint-reader#1405
* fix: Build with -fno-exceptions by @znelson in
crosspoint-reader#1412
* fix: Reduce flash usage by cleaning up I18n translations by @steka in
crosspoint-reader#1401
* fix: jpeg resource cleanup by @jpirnay in
crosspoint-reader#1320
* fix: back button in settings returns to tab bar first by @Cache8063 in
crosspoint-reader#1354
* fix: Init lastSleepImage (edge case) by @jpirnay in
crosspoint-reader#1360
* fix: Add special handling for apostrophe hyphenation by @jpirnay in
crosspoint-reader#1318
* fix: Fix inter-word spacing rounding error in text layout by @znelson
in crosspoint-reader#1311
* fix: load access fault crash by @Uri-Tauber in
crosspoint-reader#1370
* fix: Fix bootloop logging crash by @jpirnay in
crosspoint-reader#1357
* fix: dump crash log without usb plugged, bump release log to INFO by
@ngxson in
crosspoint-reader#1332
* fix: avoid zip filename overflow by @jpirnay in
crosspoint-reader#1321
* fix: Hanging indent (negative text-indent) and em-unit sizing by
@jpirnay in
crosspoint-reader#1229
* fix: Use fixed-point fractional x-advance and kerning for better text
layout by @znelson in
crosspoint-reader#1168
* fix: use HTTPClient::writeToStream for downloading files from OPDS by
@osteotek in
crosspoint-reader#1207
* fix: make file system operations thread-safe (HalFile) by @ngxson in
crosspoint-reader#1212
* fix: properly implement requestUpdateAndWait() by @ngxson in
crosspoint-reader#1218
* fix: prevent infinite render loop in Calibre Wireless after file
transfer by @pablohc in
crosspoint-reader#1070
* fix: WiFi lifecycle and hyphenation heap defragmentation for KOReader
sync by @jpirnay in
crosspoint-reader#1151
* fix: Fix coverRendered flag by @jpirnay in
crosspoint-reader#1154
* fix: Handle non-ASCII characters in sanitizeFilename by @znelson in
crosspoint-reader#1132
* fix: Update activity was missing "Back" button label by @znelson in
crosspoint-reader#1128
* fix: force auto-hinting for Bookerly to fix inconsistent stem widths
by @adriancaruana in
crosspoint-reader#1098
* fix: image centering bleed by @martinbrook in
crosspoint-reader#1096
* fix: double free WebDAVHandler by @ngxson in
crosspoint-reader#1093
* fix: Consider extra quotation styles when hyphenating quoted words by
@cbix in
crosspoint-reader#1077
* fix: acquire power lock before sleeping by @ngxson in
crosspoint-reader#1125
* fix: Unify inconsistent Wi-Fi/WiFi in Czech translation by @pepastach
in crosspoint-reader#1138
* fix: sdfat warning about redefinition of macro by @ngxson in
crosspoint-reader#1135
* fix: Close leaked file descriptors in SleepActivity and web server by
@brbla in
crosspoint-reader#869
* fix: Enable DESTRUCTOR_CLOSES_FILE flag by @daveallie in
crosspoint-reader#1075
* fix: Change "UI Font Size" to "Reader Font Size" by @divinitycove in
crosspoint-reader#1171
* fix: Hide unusable button hints when viewing empty directory by @Levrk
in crosspoint-reader#1253
* fix: broken translations in status bar settings by @ariel-lindemann in
crosspoint-reader#1188
* fix: clarity issue with ambiguous string `SET` by @ariel-lindemann in
crosspoint-reader#1169
* fix: Crash (Load access fault) when indexing chapters containing
characters unsupported by bold/italic font variants by @Uri-Tauber in
crosspoint-reader#997
* fix: Increase PNGdec buffer size to support wide images by @osteotek
in crosspoint-reader#995
* fix: Use HalPowerManager for battery percentage by @vjapolitzer in
crosspoint-reader#1005
* fix: Fix dangling pointer by @Uri-Tauber in
crosspoint-reader#1010
* fix: re-implementing Cover Outlines for the new Lyra Themes by @Levrk
in crosspoint-reader#1017
* fix: use double FAST_REFRESH to prevent washout on large grey images
by @martinbrook in
crosspoint-reader#957
* fix: Fixed Image Sizing When No Width is Set by @DestinySpeaker in
crosspoint-reader#1002
* fix: Strip unused CSS rules by @daveallie in
crosspoint-reader#1014
* fix: continue reading card classic theme by @pablohc in
crosspoint-reader#990
* fix: Destroy CSS Cache file when invalid by @daveallie in
crosspoint-reader#1018
* fix: Shorten "Forget Wifi" button labels to fit on button by
@lukestein in
crosspoint-reader#1045
* fix: improve Spanish translations by @pablohc in
crosspoint-reader#1054
* fix: Fixed book title in home screen by @DestinySpeaker in
crosspoint-reader#1013
* fix: Fix hyphenation and rendering of decomposed characters by
@jpirnay in
crosspoint-reader#1037
* fix: Improve and add Spanish translations by @DaniPhii in
crosspoint-reader#1338
* fix: improve and add Spanish translations by @DaniPhii in
crosspoint-reader#1254
* fix: improve and add Swedish translations by @steka in
crosspoint-reader#1317
* fix: Extend missing / amend existing German translations by @jpirnay
in crosspoint-reader#1226
* fix: update french.yaml file to have a better French translation of
the CFW by @Spigaw in
crosspoint-reader#1130
* fix: added romanian translation to new strings by @ariel-lindemann in
crosspoint-reader#1105
* fix: add missing romanian strings by @ariel-lindemann in
crosspoint-reader#1187
* fix: add new Ukrainian translation line for STR_SCREENSHOT_BUTTON by
@mirus-ua in
crosspoint-reader#1149
* fix: Dutch translation prefix correction by @basvdploeg in
crosspoint-reader#1223
* fix: Small typo in i18n.md regarding C++ identifiers by
@victordomingos in
crosspoint-reader#1210
* fix: typo in USER_GUIDE.md by @arnaugamez in
crosspoint-reader#1036
* fix: add missing keyboard metrics to Lyra3CoversTheme by @dexif in
crosspoint-reader#1101

### Internal
* perf: font-compression improvements by @adriancaruana in
crosspoint-reader#1056
* perf: Improve font drawing performance by @jpirnay in
crosspoint-reader#978
* perf: Replace std::list with std::vector in text layout by @znelson in
crosspoint-reader#1038
* perf: Optimize HTML entities lookup to O(log(n)) by @Uri-Tauber in
crosspoint-reader#1194
* perf: UITheme::getMetrics const and const-ref usage by @znelson in
crosspoint-reader#1094
* perf: Avoid creating strings for file extension checks by @znelson in
crosspoint-reader#1303
* perf: Eliminate per-pixel overheads in image rendering by @martinbrook
in crosspoint-reader#1293
* perf: Update github actions for optimal performance with pioarduino by
@Jason2866 in
crosspoint-reader#1080
* style: Phase 1 - Simple light dark themes by @cdmoro in
crosspoint-reader#1006
* refactor: implement ActivityManager by @ngxson in
crosspoint-reader#1016
* refactor: Simplify REPLACEMENT_GLYPH fallback by @znelson in
crosspoint-reader#1119
* refactor: Simplify new setting introduction by @jpirnay in
crosspoint-reader#1086
* refactor: Use std binary search algorithms for font lookups by
@znelson in
crosspoint-reader#1202
* refactor: rename MyLibrary to FileBrowser by @osteotek in
crosspoint-reader#1260
* refactor: Avoid rebuilding cache path strings by @znelson in
crosspoint-reader#1300
* refactor: reader utils by @Uri-Tauber in
crosspoint-reader#1329
* chore: Remove miniz and modularise inflation logic by @daveallie in
crosspoint-reader#1073
* chore: Resolve several build warnings by @daveallie in
crosspoint-reader#1076
* chore: Removed generated language headers by @znelson in
crosspoint-reader#1156
* chore: Added generated lang headers to .gitignore by @znelson in
crosspoint-reader#1158
* chore: remove redundant xTaskCreate by @ngxson in
crosspoint-reader#1264
* chore: Removed unused PlatformIO include directory placeholder by
@znelson in
crosspoint-reader#1417
* chore: micro-optimisation: early exit on fillUncompressedSizes by
@jpirnay in
crosspoint-reader#1322
* chore: change label while on settings tab actions by @jpirnay in
crosspoint-reader#1325
* chore: add firmware size history script by @znelson in
crosspoint-reader#1235
* chore: Add powershell script for clang-formatting by @jpirnay in
crosspoint-reader#1472
* chore: Removed unused ConfirmationActivity member by @znelson in
crosspoint-reader#1234
* chore: Update russian.yaml by @madebyKir in
crosspoint-reader#1198
* chore: new Ukrainian translation lines by @mirus-ua in
crosspoint-reader#1199
* chore: new Ukrainian localization strings by @mirus-ua in
crosspoint-reader#1270
* chore: Polish localization for STR_DELETE by @JonaszPotoniec in
crosspoint-reader#1323
* chore: Image settings Polish localization by @znelson in
crosspoint-reader#1299
* chore: add missing Catalan strings by @angeldenom in
crosspoint-reader#1302
* chore: add missing translations for Romanian by @ariel-lindemann in
crosspoint-reader#1265
* chore: Add Portuguese (Portugal) translator to the list by
@victordomingos in
crosspoint-reader#1211
* chore: Reduce flash usage by cleaning up I18n translations by @steka
in crosspoint-reader#1401
* docs: Add lightweight contributor onboarding documentation by @bilalix
in crosspoint-reader#894
* docs: ActivityManager migration guide by @znelson in
crosspoint-reader#1222
* docs: USER_GUIDE.md update for 1.1.0 by @divinitycove in
crosspoint-reader#1108
* docs: add quick KOReader sync setup guide by @wjhrdy in
crosspoint-reader#1181
* docs: image support marked as completed by @ariel-lindemann in
crosspoint-reader#1008
* feat: aiagent context definition by @jpirnay in
crosspoint-reader#922
* chore: Update SKILL.md to reflect generated i18n files are gitignored
by @znelson in
crosspoint-reader#1423
* fix: ActivityManager tweaks by @znelson in
crosspoint-reader#1220
* fix: Correct relative file paths in SKILL.md documentation by @pablohc
in crosspoint-reader#1304
* fix: add Technically Unsupported section to SCOPE.md by @Uri-Tauber in
crosspoint-reader#1295

## New Contributors
* @DestinySpeaker made their first contribution in
crosspoint-reader#1002
* @arnaugamez made their first contribution in
crosspoint-reader#1036
* @angeldenom made their first contribution in
crosspoint-reader#1049
* @cdmoro made their first contribution in
crosspoint-reader#1006
* @bilalix made their first contribution in
crosspoint-reader#894
* @Jessica765 made their first contribution in
crosspoint-reader#682
* @brbla made their first contribution in
crosspoint-reader#869
* @dexif made their first contribution in
crosspoint-reader#1047
* @mirus-ua made their first contribution in
crosspoint-reader#1065
* @cbix made their first contribution in
crosspoint-reader#1077
* @divinitycove made their first contribution in
crosspoint-reader#1108
* @pepastach made their first contribution in
crosspoint-reader#1138
* @Jason2866 made their first contribution in
crosspoint-reader#1080
* @andreaturchet made their first contribution in
crosspoint-reader#1144
* @Spigaw made their first contribution in
crosspoint-reader#1130
* @iandchasse made their first contribution in
crosspoint-reader#1141
* @th0m4sek made their first contribution in
crosspoint-reader#1155
* @plahteenlahti made their first contribution in
crosspoint-reader#1133
* @hajisan made their first contribution in
crosspoint-reader#1146
* @madebyKir made their first contribution in
crosspoint-reader#1198
* @victordomingos made their first contribution in
crosspoint-reader#1210
* @basvdploeg made their first contribution in
crosspoint-reader#1204
* @wjhrdy made their first contribution in
crosspoint-reader#1181
* @DaniPhii made their first contribution in
crosspoint-reader#1254
* @steka made their first contribution in
crosspoint-reader#1317
* @barbarhan made their first contribution in
crosspoint-reader#1192
* @JonaszPotoniec made their first contribution in
crosspoint-reader#1323
* @Cache8063 made their first contribution in
crosspoint-reader#1354
* @fsocietyipa made their first contribution in
crosspoint-reader#1377
* @LSTAR1900 made their first contribution in
crosspoint-reader#979
* @zgredex made their first contribution in
crosspoint-reader#1224

**Full Changelog**:
crosspoint-reader/crosspoint-reader@1.1.1...release/1.2.0

---------

Co-authored-by: jpirnay <jens@pirnay.com>
Co-authored-by: Dani Poveda <daniphii@outlook.com>
Co-authored-by: Baris Albayrak <80099286+barbarhan@users.noreply.github.com>
Co-authored-by: Barış Albayrak <barisa@pop-os.lan>
Co-authored-by: Stefan Blixten Karlsson <sbkarlsson@gmail.com>
Co-authored-by: Àngel <153315454+angeldenom@users.noreply.github.com>
Co-authored-by: Jonasz Potoniec <jonasz@potoniec.eu>
Co-authored-by: Егор Мартынов <martynovegorOF@yandex.ru>
Co-authored-by: Mirus <mirusim@gmail.com>
Co-authored-by: Spigaw <73850535+Spigaw@users.noreply.github.com>
Co-authored-by: ariel-lindemann <41641978+ariel-lindemann@users.noreply.github.com>
Co-authored-by: Nima Salami <54304457+hajisan@users.noreply.github.com>
Co-authored-by: Arthur Tazhitdinov <lisnake@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Bas van der Ploeg <bas@basvanderploeg.nl>
Co-authored-by: martin brook <martin.brook100@googlemail.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.

5 participants