Repository navigation
KitePDF 0.11.0
KitePDF 0.11.0 now adds XPS (and OpenXPS) format support. It can finally run the JavaScript inside PDF forms (thanks to KiteJS integration), and closes more than a hundred issues (156 issues in total). Six of them break-change the API (they are marked 🔴 below).
Note that Javascript integration is still experimental and only runs in PDF forms. Javascript in EPUBs is still not supported (planned for v0.12.0 probably).
Usage
// Every format: PDF, EPUB, CBZ, SVG, XPS and OpenXPS
implementation("io.github.yuroyami:kitepdf:0.11.0")
// Or one format only
implementation("io.github.yuroyami:kitepdf-pdf:0.11.0")
implementation("io.github.yuroyami:kitepdf-epub:0.11.0")
implementation("io.github.yuroyami:kitepdf-cbz:0.11.0")
implementation("io.github.yuroyami:kitepdf-svg:0.11.0")
implementation("io.github.yuroyami:kitepdf-xps:0.11.0") // new in 0.11.0
// Optional (but you may probably need one of these depending on your use case)
implementation("io.github.yuroyami:kitepdf-compose-viewer:0.11.0") // KiteDocView for Compose Multiplatform (renderer)
implementation("io.github.yuroyami:kitepdf-native-renderer:0.11.0") // page-to-image on the platform canvas (headless+renderer)
implementation("io.github.yuroyami:kitepdf-skia-renderer:0.11.0") // page-to-image on Skia multiplatform (headless+renderer)
implementation("io.github.yuroyami:kitepdf-javascript:0.11.0") // runs the JavaScript inside PDFs (pulls KiteJS artifact)
implementation("io.github.yuroyami:kitepdf-net:0.11.0") // allows KitePDF to remotely load documents from a URLkitepdf-core arrives with every handler. Do not add it yourself.
Changelog
🔴 Breaking changes
| Change | What to do |
|---|---|
#234: PdfScriptRunner.onAlert is now (PdfScriptAlert) -> Int, and formState and policy are new 2nd and 3rd parameters |
Update onAlert, and pass arguments by name |
#196: KiteShading.FlatQuad is gone, and PatchMesh.quads is now patches plus colorTable |
Read PatchMesh.patches |
#238: PdfAnnotation has a new additionalActions parameter before raw |
Pass raw by name |
#205: KiteDocFormat has a new Xps value |
Handle Xps in a when that has no else |
#113: KiteCanvas has a new drawImage overload with a blend mode |
Override both overloads in a by wrapper |
#68: KiteCanvas has a new applySoftMask overload with a transfer function |
Override both overloads in a by wrapper |
The last two still compile. A wrapper that overrides only the old overload silently misses those calls.
Everything since 0.10.0
| Area | Type | Change |
|---|---|---|
| CBZ (1) | New Features | #206: Read a comic archive's ComicInfo.xml into its metadata and outline |
| Core (27) | New Features | #197: Bundled outlines for the 14 standard fonts, so every host renders them the same |
| #199: Added support for CFF2 fonts and TrueType collections | ||
| #200: Converted colours through lookup-table ICC profiles instead of a device space | ||
| #211: Added contextual substitution and Indic reordering | ||
| a7541c7: Converted DeviceCMYK through a PDF/X file's CMYK output intent, as MuPDF does | ||
| API Changes | 🔴 #113: Drew images with the blend mode of the graphics state, through a new drawImage overload | |
| Performance | #119: Lexed numbers and keywords without allocating a String or a parse buffer | |
| #185: Transformed path and glyph points without allocating a pair for each point | ||
| Fixes | 🔴 #68: Applied a soft mask's /BC backdrop and /TR transfer function | |
| #72: Kept the declared colour space and /Decode array of JPEG images | ||
| #126: Removed the pale seams between mesh and patch shading cells | ||
| #140: Placed CFF and Type 1 outlines by their own font matrix, not a fixed 1000 units per em | ||
| #159: Undid the /Matte preblend (premultiplied alpha) of soft-masked images | ||
| #160: Read a /Mask that points at a multi-bit image without the stencil flag as a soft mask | ||
| 🔴 #196: Rasterized mesh shadings on their exact surface, with smooth colours and every tensor control point | ||
| #198: Selected the right glyphs in Unicode-keyed CJK documents | ||
| #279: Read every glyph of an embedded Type 1 font, including the first ones in its CharStrings | ||
| #280: Picked the glyphs of CID-keyed CFF fonts through the charset | ||
| #282: Drew fonts embedded as /FontFile3 /Subtype /OpenType with their own outlines | ||
| #298: Drew text in a non-embedded standard 14 font from the bundled outlines | ||
| #299: Converted DeviceCMYK colours the way MuPDF and PDFium do | ||
| #302: Confirmed that JPEG 2000 decoding matches OpenJPEG, and scored the small drawing difference as rounding | ||
| #303: Drew accented letters in embedded Type1C fonts | ||
| #304: Drew the right ZapfDingbats symbols for codes from 128 up | ||
| #305: Kept ZapfDingbats symbols in text extraction | ||
| #309: Drew text in a non-embedded CJK font that has no ToUnicode map | ||
| #311: Kept grey content neutral under an ICC grey profile whose white point is not D50 | ||
| Docs (1) | Fixes | #307: Removed the stale AGPL note from the README, and listed what KitePDF bundles |
| EPUB (28) | New Features | #26: Rendered and named SVG chapters, and sized fixed-layout SVG pages |
| #317: Reordered Sinhala, Khmer, Myanmar and Tibetan, and split Thai sara am, as HarfBuzz does | ||
| API Changes | #227: Exposed semantic EPUB link targets and fragment content for a host's footnote UI (reported by @ksokolovskiy) | |
| Fixes | #100: Kept images upright in vertical writing | |
| #101: Painted the frame and background of framed figures | ||
| #103: Drew underlines and strikethroughs | ||
| #104: Used an embedded typeface that is listed after an unavailable family | ||
| #168: Painted inline background colours, so highlighted spans show | ||
| #170: Kept cover-fitted images in proportion in vertical writing | ||
| #172: Painted block images and text in document order (CSS 2.1, Appendix E) | ||
| #210: Resolved collapsed table borders by style and width | ||
| #253: Kept the alpha of inline backgrounds, so the text stays visible | ||
| #257: Resolved a system-ui font stack to sans-serif instead of serif | ||
| #259: Kept a space between two inline elements at its normal width and in copied text | ||
| #261: Placed inline images in vertical-lr text in their own column | ||
| #265: Kept underlines out of inline-block and floated content | ||
| #271: Kept an underline's colour and thickness inside styled child elements | ||
| #275: Drew SVGs inside inline elements, and gave hidden SVGs no space | ||
| #276: Loaded an inline SVG's images from its chapter's folder | ||
| #314: Kept every character that a ligature draws in the page text | ||
| #315: Joined Arabic letters by Unicode's joining types, also next to a hamza or a direction mark | ||
| #316: Composed decomposed accented letters into one glyph before GSUB | ||
| #318: Ordered Syriac marks and Arabic modifier marks as HarfBuzz does | ||
| #319: Drew characters outside the Basic Multilingual Plane from the book's font | ||
| #320: Laid out Syriac, Thaana, N'Ko and the other right-to-left scripts right to left | ||
| #321: Mirrored brackets in right-to-left text, and applied ltrm and rtlm | ||
| #322: Applied text-transform to letters outside the BMP | ||
| #323: Implemented the whole Unicode Bidirectional Algorithm, with explicit controls, combining marks and paired brackets | ||
| JavaScript (8) | New Features | #230: Gave scripts the document and field objects that Acrobat scripts use |
| #231: Added the Acrobat helper functions, AFNumber_Format and AFSimple_Calculate included | ||
| #232: Ran the calculate, format, validate and keystroke scripts of form fields | ||
| #233: Ran a document's scripts in the viewer on open and on script links, when the app passes a script handler | ||
| #241: Added script timers: app.setInterval and app.setTimeOut | ||
| #246: Ran DoomPDF, the Doom port that lives inside a PDF, at 11.5 frames a second | ||
| API Changes | 🔴 #234: Let the host choose which documents run scripts, and for how long, with PdfScriptPolicy | |
| #242: Ran document scripts on their own thread, so a long script cannot freeze the viewer | ||
| PDF (29) | New Features | #188: Made a page render cancellable between operators |
| #237: Exposed a page's open and close scripts and the document's open action | ||
| 🔴 #238: Exposed a form widget's press, release, focus and keystroke scripts | ||
| #243: Showed a value that a script sets on a field right away, without saving and reopening | ||
| Performance | #116: Gave the decoded image cache a 32 MB byte budget, and let apps drop it | |
| #118: Parsed a page's content once per document instead of on every render | ||
| #293: Lexed each content stream token once | ||
| Fixes | #57: Hid print-only layers on screen | |
| #85: Drew outlined text in a font that has no embedded program | ||
| #88: Filled gradient headlines with their gradient instead of flat black | ||
| #93: Placed shading pattern fills in their stream's space | ||
| #94: Painted uncoloured tiling patterns in the requested colour | ||
| #114: Resolved page colour spaces that inline images name | ||
| #124: Laid out vertical CJK text in columns | ||
| #127: Rendered fillable forms that have no appearance streams | ||
| #150: Substituted page-level default colour spaces for device colours | ||
| #164: Drew sticky notes, attachments, carets, stamps and free text that have no appearance | ||
| #239: Read form fields that exist only as page widgets, with no AcroForm | ||
| #240: Drew form fields without an appearance stream, check boxes and radio buttons included | ||
| #249: Kept every widget of a form field, so a radio group keeps all its buttons | ||
| #252: Read a broken reference in the layer usage rules as null, so every page still renders | ||
| #254: Ended inline images at EI, so a wrong colour space size cannot swallow the page | ||
| #266: Split inline images the same way in text extraction, redaction and rendering | ||
| #273: Resolved indirect page boxes, resources and form geometry | ||
| #274: Added invisible, outlined and Type 3 text to search and selection | ||
| #278: Redacted all text that the renderer draws inside the region | ||
| #281: Embedded OpenType CFF fonts at their true size in PdfBuilder | ||
| #284: Painted pattern strokes inside the stroke outline | ||
| #290: Kept images visible to canvas wrappers that override the three-argument drawImage | ||
| Rendering (28) | Performance | #117: Converted an image once per canvas and reused the bitmap |
| #130: Stopped building a new path object for every fill, stroke and glyph | ||
| #256: Sped up AWT soft masks by compositing the masked content as one layer | ||
| #306: Sped up dense text on AWT by rasterizing each glyph once | ||
| Fixes | #69: Mapped axial and radial shadings by the whole CTM, so elliptical gradients stay elliptical | |
| #70: Honoured shading /Extend on Compose, Android, CoreGraphics and Canvas2D | ||
| #71: Drew radial gradients between both circles, so they keep their highlight | ||
| #77: Composited AWT transparency groups once, with their alpha and blend mode | ||
| #78: Kept the content painted before an AWT soft mask | ||
| #79: Stopped painting a soft mask group's own colours onto the page | ||
| #80: Applied AWT soft masks on surfaces with no alpha channel | ||
| #105: Handled single-element dash arrays on Android | ||
| #108: Stroked with an elliptical pen under a non-uniform matrix | ||
| #109: Drew zero-width lines one device pixel wide on every backend | ||
| #110: Gave thin strokes one floor on every backend, so thin rules on Skia and Compose match mutool | ||
| #121: Placed non-embedded text runs at the document's advances on every backend | ||
| #122: Stopped point-sampling downsampled images, so thin strokes stay visible | ||
| #123: Sampled scaled-up images by one rule on every backend | ||
| #125: Honoured group isolation and knockout flags on every backend | ||
| #161: Applied soft masks on the browser canvas, for both mask kinds | ||
| #255: Kept soft-masked content on AWT when the mask group's box is a reference | ||
| #264: Applied soft masks on AWT renders above 40 megapixels | ||
| #272: Applied blend modes on AWT surfaces with no alpha channel | ||
| #285: Anti-aliased the edges of AWT clips | ||
| #288: Made ApplePdfRasterizer run, and draw the page upright | ||
| #289: Drew images upright on CoreGraphics | ||
| #300: Moved image edges onto whole pixels, as MuPDF does | ||
| #301: Resampled scaled images as MuPDF does | ||
| SVG (10) | Fixes | #89: Applied the colours from an SVG's style element |
| #177: Resolved percentage geometry in SVG | ||
| #179: Rendered reflect and repeat gradients | ||
| #180: Applied gradient stop opacity | ||
| #181: Placed each character of SVG text from its position lists | ||
| #263: Sized SVG images with an empty or unreadable width from their ratio | ||
| #269: Styled clip path content by its own ancestors | ||
| #283: Painted gradient fills inside their shape | ||
| #286: Painted SVG gradient strokes with their gradient | ||
| #292: Painted no stroke for an SVG stroke width of 0 | ||
| Tests and CI (10) | New Features | #297: Scored renders against PDFium too, and failed a page where PDFium does better |
| Fixes | #223: Ran the CI differential gate against a pinned MuPDF 1.27.2 with colour management | |
| Tests | #193: Documented which platforms CI tests, which it only compiles, and which it does not check | |
| #195: Checked each page of the differential gate against its own recorded score | ||
| #202: Checked the public API of each published module against a dump in CI | ||
| #260: Made the deflate oracle test read the CI oracle, and report SKIPPED when it cannot run | ||
| #270: Uploaded the XPS raster output in CI when the XPS raster test fails | ||
| #295: Failed the oracle tests when mutool has to repair a PDF that KitePDF wrote | ||
| #296: Made the encrypted output test check that mutool refuses the file without its password | ||
| #310: Kept SelectionSceneTest drags clear of the long-press timeout | ||
| Viewer (11) | New Features | #244: Let readers type into text fields, through the document's own scripts |
| #245: Sent a push button press to the document's scripts | ||
| #251: Added state.currentScrollPosition, to save and restore the scroll offset (reported by @Tulis12) | ||
| API Changes | #132: Let apps pass a canvasDecorator that wraps the viewer's paint pass | |
| #277: Added onEpubReferenceTap, so the host can show an EPUB footnote in place | ||
| #291: Let apps handle a tap on one of their saved highlights | ||
| Fixes | #229: Rasterized a visible page once while chapters load | |
| #258: Kept the reported page when the continuous viewer leaves the screen | ||
| #262: Clamped a start page past the end to the last page | ||
| #294: Made PagedAnchorSceneTest wait on the wall clock for the loader | ||
| #313: Kept the selection when a finger rests on a handle | ||
| XPS (4) | New Features | 🔴 #205: Added an XPS and OpenXPS handler |
| Fixes | #267: Kept XPS text with a gradient or image fill when its font is missing | |
| #268: Clipped XPS content only by filled figures | ||
| #287: Applied SpreadMethod to XPS gradient brushes |
Dependencies
| Version | |
|---|---|
| Kotlin | 2.4.20 |
| Compose Multiplatform | 1.12.1 (kitepdf-compose-viewer) |
| 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) |
| KiteImage | 0.1.0 (kitepdf-core) |
| 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.10.0...v0.11.0