Skip to content

KitePDF 0.12.0

Choose a tag to compare

@yuroyami yuroyami released this 29 Sep 20:20

KitePDF 0.12.0 now checks the digital signatures of a signed PDF, and decodes big scans at the size they are drawn, so a 600 dpi page on a phone no longer needs hundreds of megabytes. EPUB books gain MathML, flex, grid and multi-column layout, every format gets a reading order for screen readers, and the release closes more than a hundred issues (127 issues in total). Two changes break the API (they are marked 🔴 below). The biggest thing about this update is that it brings major performance enhancements to the Compose renderer, and fixes a plethora of issues most of which caused crashes.

Usage

// Every format: PDF, EPUB, CBZ, SVG, XPS and OpenXPS
implementation("io.github.yuroyami:kitepdf:0.12.0")

// Or one format only
implementation("io.github.yuroyami:kitepdf-pdf:0.12.0")
implementation("io.github.yuroyami:kitepdf-epub:0.12.0")
implementation("io.github.yuroyami:kitepdf-cbz:0.12.0")
implementation("io.github.yuroyami:kitepdf-svg:0.12.0")
implementation("io.github.yuroyami:kitepdf-xps:0.12.0")

// Optional (but you may probably need one of these depending on your use case)
implementation("io.github.yuroyami:kitepdf-compose-viewer:0.12.0")   // KiteDocView for Compose Multiplatform (renderer)
implementation("io.github.yuroyami:kitepdf-native-renderer:0.12.0")  // page-to-image on the platform canvas (headless+renderer)
implementation("io.github.yuroyami:kitepdf-skia-renderer:0.12.0")    // page-to-image on Skia multiplatform (headless+renderer)
implementation("io.github.yuroyami:kitepdf-javascript:0.12.0")       // runs the JavaScript inside PDFs (pulls KiteJS artifact)
implementation("io.github.yuroyami:kitepdf-net:0.12.0")              // allows KitePDF to remotely load documents from a URL

kitepdf-core arrives with every handler. Do not add it yourself.

Changelog

🔴 Breaking changes

Change What to do
#449: KiteLinkAction.Uri is gone, and KiteLinkAction has the new kinds Epub and Plain Read link.uri, or add Epub and Plain to a when without else
#449: KiteDocView no longer takes onEpubReferenceTap Check link.kind in onLinkTap
2fe3273: kitepdf-core no longer passes its image engine, now KiteImageCodec, on to apps If you call the engine directly, add io.github.yuroyami:kiteimagecodec:0.2.0, import io.github.yuroyami.kiteimagecodec, and call KiteImageCodec.decode

Two changes still compile. onLinkTap now also receives links inside the document before the viewer follows them, so a callback that returns true for every link stops that navigation (#449). KiteSelectionMenu now sits next to the selection by default. Pass an alignment to pin it as before (#408).

Everything since 0.11.0

AreaTypeChange
Viewer (60)New Features#410: Flung the pan of a zoomed page, and turned the page past its edge
#411: Zoomed with Ctrl and the wheel, paged and zoomed with the keyboard, and selected text with a mouse drag
#433: Brought a linked place to the top at any zoom and layout, turned the page for named links, and ran script links
#444: Let the app see an internal EPUB link before the viewer follows it, to show a note in place (reported by @ksokolovskiy)
API Changes#30: Added pageOverlay, pageRectToViewport and displayRectToViewport, to place a composable over a rectangle on a page
#408: Placed the selection menu next to the selection, and added selectionBounds for hosts that place their own
#429: Moved a state's suspend calls onto the viewer's thread, so an app can navigate from any thread
#431: Let KitePageRasterizer.rasterize take a form state, to export a filled form
#432: Added hitTestDisplay, which gives a hit in display space for every format
🔴 #449: Gave onLinkTap every link in every format before the viewer acts, with uri, target, kind, pageIndex and rect on each link
acbe57d: Passed Compose runtime, foundation and ui on to apps, since KiteDocView's API takes and returns their types
Performance#370: Rendered two pages at once, the visible one first, with cancellation for every format
#372: Gave a Vectorized page its own layer, so an overlay change no longer redraws it
#373: Moved the layer on a zoom or pan frame, with no recomposition
#374: Recomposed the page widgets only when the reader crosses a page
#375: Drew the part on screen in tiles past the bitmap cap, so deep zoom stays sharp
#376: Rasterized a settled zoom only for the pages in view
#380: Built a page's text off the main thread before a long press selects it
#390: Rasterized a page once a resize holds, not on every frame
#391: Cached thumbnails, and kept one EPUB outline per state
#393: Put decoded pixels into a bitmap once on Skia targets
#394: Kept a themed page's raster when only the page background changes
#395: Freed the page cache when its budget is zero or the view is Vectorized
a0ebaa7: Rendered a page drawn in a host font once, not twice
e75ca6a: Let a soft mask's canvas share the image bitmaps of its page
e8a5c53: Converted each glyph outline to a path once per draw
Fixes#332: Laid out very tall and very wide pages in the Continuous layout
#338: Ignored zoom input that is not finite, and checked doubleTapZoom and offscreenPages
#342: Kept the reader on their page when a chapter lands above them in the Continuous layout
#343: Ran the Paged correction for a long chapter that lands, in an app as in tests
#344: Kept the jump to a bookmark going when the reader drags while a book opens
#345: Made the viewer state the only saved reading position
#346: Took the position of a new KiteDocViewState under the same KiteDocView
#348: Landed on the last page of a loading chapter when the reader pages back onto it
#350: Kept a selection drag going while a chapter lands
#352: Kept the position when Continuous switches between vertical and horizontal
#353: Letterboxed a chapter placeholder in a pager like a page
#392: Confirmed that a Vectorized page and a pool raster of one document draw safely at once
#397: Let the reader reach both ends of a zoomed Continuous strip
#398: Made swiping, panning and the opening zoom work with any minZoom
#399: Kept a zoomed page in view when the viewer changes size
#400: Bounded the pan by the page, so a zoomed page no longer slides into empty margins
#401: Placed spread pages from the left in a right-to-left app, so a tap finds the right page
#402: Updated the page indicator on a page step inside one spread
#403: Kept a set zoom when a Paged or Spread layout appears
#404: Applied a changed pan setting to the next two-finger pan
#405: Let a finger or a zoom request stop a running zoom animation
#406: Placed selection handles on the ends of the text in every writing direction
#407: Dropped a selection that a navigation leaves behind, so scrolling unlocks
#409: Gave a chapter placeholder in a pager the taps, double taps and pinches of a page
#417: Drew a Vectorized page only inside its slot
#418: Drew a Vectorized page again at the settled zoom, with sharp images and thin hairlines
#419: Painted placeholders, chapter gaps, thumbnails and form widgets in the reader theme
#420: Kept the cached pixels of two reader themes apart
#421: Rendered a page again when the font environment changes
#422: Drew a page at every accepted raster quality
#430: Kept a page's last bitmap when its raster fails, and let the app see and retry the failure
#435: Kept every argument in the IDE quick fixes of the deprecated PdfView and EpubView
ed0f7ab: Reported the reader's page exactly between a chapter landing and the next measure
Docs#436: Made the viewer's KDoc say what the code does
PDF (11)New Features#203: Validated digital signatures: CMS, PKCS #1, RSA-PSS and ECDSA, with the certificate chain, time stamps and a check for changes after signing
#204: Drew rich-text form fields, and wrapped the text of multi-line fields
#447: Reported whether a signature's certificate was revoked, from the CRL and OCSP data in the file or given by the app
#448: Judged each change made after a signature against the permissions of a certification signature and a field lock
Performance#383: Parsed each font once per document, within a memory budget, instead of once per page render
#387: Built the page list of a large PDF off the main thread
Fixes#329: Opened a PDF whose page count is wrong as the pages it really holds
#330: Opened a PDF page whose page box cannot be read, instead of crashing
#333: Kept the app running when a page or the form layer fails to draw
#334: Kept the app running after a tap or a long press on a malformed page
#441: Read and drew a form whose entries point at missing objects
EPUB (31)New Features#27: Followed the manifest's fallback chain for a resource the engine cannot render, and showed one branch of an epub:switch
#28: Painted opacity, overflow, visibility, 2D transforms, rounded corners, box shadows, background images and linear gradients in fixed-layout books
#29: Gave audio and video elements a box on the page, and listed them in EpubPage.media
#32: Rendered presentation MathML: fractions, scripts, limits, radicals, tables and stretching fences
#33: Laid out display: flex, so flex pages no longer stack vertically
#34: Laid out multi-column blocks in columns
#35: Laid out display: grid
#37: Read the spread, orientation and layout rendition properties, and paired spreads as the book declares
#39: Carried pronunciation hints into the reading order, for speech
#40: Flagged chapters that hold scripts, and gave embedded documents a box
f29e16d: Read media overlays, and found the page that holds a text fragment
Performance#351: Opened one page of a book in KiteDocView(document, page) without laying out the whole book
#377: Laid out a chapter that the memory budget dropped off the UI thread
#378: Kept one chapter loader running while the reader scrolls past unloaded chapters
#379: Took a bookmark or a page step on a chapter placeholder without a layout on the caller's thread
#388: Let iOS and macOS threads sleep while a chapter lays out, instead of spinning
06781d4: Laid out far chapters in a browser only while the reader rests
Fixes#331: Kept the app running when a chapter fails to lay out
#336: Let SinglePage show any valid page of a book that is still laying out
#337: Laid out a book in spreads behind the reader, off the UI thread, with no blank spreads
#341: Showed a chapter that was laid out outside the viewer's loader, instead of a blank placeholder
#347: Kept the reader in an empty chapter, instead of jumping to the last page of the book
#349: Found a page bookmark's page before the book is laid out
#396: Counted chapters that hold only an SVG toward the layout memory budget
#423: Honoured page breaks on containers, tables and images
#424: Gave an image with display: none no box
#425: Resolved an inline SVG image's own links from its own folder
#426: Scaled a tall inline image to the page, so it is no longer cut off
#434: Restored a bookmark on the right page after the font family changes
#438: Copied a book's text without the layout's line breaks and hyphens
#442: Kept a page-tall image at the start of a paragraph on its page
Forms and scripts (16)Performance#368: Pumped script timers only while one waits, not on every frame
Fixes#355: Kept each script engine on one thread of its own
#356: Kept the caret in a tapped text field, so the reader can type
#357: Repainted the form when a check box, radio button or push button is tapped
#358: Drew live form values in every layout and render mode
#359: Acted on the widget under the finger, so a tap edits the right field
#360: Let a tap pass through a widget that a script hid
#361: Ran a push button's own action, so Reset, Submit and Print work
#362: Put the hidden form input inside the viewer, over its widget, with multi-line editing
#363: Ran keystroke scripts in typing order, so a refused key no longer drops later typing
#364: Guarded the form state that scripts write from their own thread
#365: Called a document's open scripts once, and kept the app running when a script fails
#366: Ran each page's open and close scripts as the reader lands on it
#367: Timed script timers on the runner's clock, so none fires at once
#439: Gave the default values back on a form reset
#440: Let a tap clear a selected radio button in a group that allows no selection
Images (1)Performance#381: Decoded a PDF's JPEG and JPEG 2000 images at the size they draw, and converted large images a band of rows at a time
Accessibility (3)New Features#208: Gave every page a reading order for a screen reader, from a tagged PDF's structure
25506fe: Named pages, page buttons, thumbnails and colours for a screen reader
f4539f9: Gave a screen reader the text, links and form fields of each page
Rendering (8)Performance#384: Opened the two layers of a soft mask over the mask's box only
Fixes#335: Applied each clip once on the Compose canvas, and capped the clips a page can open
#412: Painted Multiply on Android 7 to 9
#413: Drew an off-centre radial gradient on Android 7 to 11
#414: Applied a soft mask's whole transfer table on Skia targets
#415: Stroked and clipped system-font text with real glyph outlines
#416: Kept shear and reflection in system-font text
#445: Applied a soft mask's whole transfer table on Android
XPS and SVG (2)New Features8a4eea0: Drew SVG pattern paint servers and masks
Performance#385: Read an XPS page's size from its start tag, and kept parsed pages under a budget
CBZ (1)Performance#386: Read a comic page's size from its image header, and decoded each scan once
Tests and CI (4)Tests#212: Built a consumer project against the published artifacts in CI
#213: Put the timing-sensitive suites back into the gate
#328: Made scene tests fail on a timeout, and run effects in the order an app does
#443: Brought viewer effects back to the composition thread after a wait, so a scene test no longer fails now and then

Dependencies

Version
Kotlin 2.4.20
Compose Multiplatform 1.12.1 (kitepdf-compose-viewer, passed on to apps)
Android Gradle Plugin 9.4.1 (built with)
Gradle 9.8.0 (built with)
JDK 21
Android SDK compileSdk 37, minSdk 21 (kitepdf-compose-viewer 24, kitepdf-native-renderer 29)
KiteImageCodec 0.2.0 (kitepdf-core, kept inside it; it was KiteImage 0.1.0)
KiteJS 0.2.0 (kitepdf-javascript)
Ktor 3.6.0 (kitepdf-net)
Skiko 0.150.1 (kitepdf-skia-renderer, kitepdf-compose-viewer)

Targets: Android, JVM, iOS, tvOS, watchOS, macOS, Linux, Windows, Android Native, JS and Wasm. kitepdf-javascript has no tvOS, watchOS, Android Native or wasmWasi build. The viewer and the renderers build for fewer targets. The platforms page lists them.

Full changelog: v0.11.0...v0.12.0