
Building an Android HWP viewer: rhwp in a WebView, measured on 222 documents
Running the open-source rhwp engine inside an Android WebView, 221 of 222 Korean HWP and HWPX files opened on a Galaxy S21, with a median of 1.2 to 1.5 seconds from tap to first page.
221 of 222 Korean word-processor files opened. Before writing HWP Viewer SugarDoc, we wanted to know whether the engine could carry an app at all, so on October 3, 2026 we opened every file from a cold start on a Galaxy S21 (Android 15, WebView 153). The engine passed, with two catches. Drawing every page of a 384-page file pushed the WebView renderer to 2.8 GB, and the set the first report called "24 government documents" held only 17 real government attachments.
Numbers come from the engine spike report in SugarMount's app repository (sugar-utils; measured 2026-10-03, commit 7b0e567), the follow-up verification report (2026-10-05), and a recount from the raw result JSON done while writing this note. Checked on October 19, 2026.
Contents (8)
HWP, HWPX and why a viewer is hard
HWP is the file format of Hancom Office Hangul, the word processor that Korean government offices, schools and many employers still use. HWP 5 is a binary compound file; HWPX is the newer ZIP-and-XML version; very old files are HWP 3.0. On a phone they usually arrive as attachments in KakaoTalk (Korea's main messenger) or email.
Layout is the hard part. Government press releases lean on dense tables, logos and fixed line breaks, and exam papers add equations and two-column pages.
Setup: one phone, 222 files, a cold start each time
rhwp is an open-source HWP/HWPX parser written in Rust and compiled to WebAssembly. It renders each page as SVG and is MIT-licensed. We used the npm package @rhwp/core 0.8.6, and the shipped app is still pinned to that version.
The test app was a single WebView with rhwp and the font stylesheet rhwp ships (153 font rules). For every file the app was force-stopped and relaunched; the first three pages went into the DOM and the rest were only timed.
- Attachments from Korea's government policy portal, korea.kr: 17 files downloaded on 2026-10-02 (14 press releases; 13 HWPX, 4 HWP).
- 198 samples from the rhwp repository, each with a reference PDF printed from Hancom Office 2020 or 2022, so page counts and first-page images can be compared. Many are hard cases: exam papers, equations, converted HWP 3.0 files.
- Seven more files, explained in the section on what the AI got wrong.
We had no low-end phone.
Results: 221 of 222 opened
"Tap to first page" is app launch time plus first-page render time, so it includes the cold start. p90 is the value where the slowest 10% begin. Renderer memory is the PSS (proportional set size: private memory plus a fair share of shared pages) of the WebView renderer process.
| Metric | korea.kr, 17 files | First report's "24 government documents" | rhwp samples, 198 |
|---|---|---|---|
| Opened | 17/17 | 24/24 | 197/198 |
| Tap to first page, median | 1.4 s | 1.5 s | 1.2 s |
| Tap to first page, p90 | 1.6 s | 2.1 s | 1.9 s |
| Tap to first page, max | 1.8 s | 3.0 s | 3.3 s |
| Render per page, median | - | 10 ms | 6 ms |
| Renderer memory (PSS), max | 286 MB | 391 MB | 422 MB |
The one failure, issue2063_huge_cellbreak_table.hwp, is a stress test built around a giant table split across pages; it ran past the 120-second limit. The spike report made a fallback path a condition for adopting the engine, and the app now lets you keep waiting or hand the file to another app after 10 seconds.
Fidelity held up. Against the reference PDFs, page counts matched for 195 of 197 samples (the other two were one page off), and the median first-page image similarity was 0.997. We also put seven files (two press releases, five samples) side by side with Hancom's output. The press-release tables, logos and bold text and the exam paper's equations and two columns looked nearly the same. The one visible miss was the first question number, "문1)", dropped from one exam paper.
A 384-page file only works if you draw the visible pages
One rhwp sample is a 384-page government administration handbook (10.7 MB). With every page's SVG in the DOM, the WebView renderer process grew to 2.8 GB. Drawing only the visible pages, the same file sat at 255 MB in one run and 366 MB in another run the same afternoon.

If you build an HWP viewer on a WebView, put virtual scrolling (only the visible pages and their neighbours in the DOM) in from day one.
The shipped viewer gives every page an empty slot of the right size and keeps SVG only for the visible pages plus two on each side, or one on each side on low-memory devices. Rendered SVG strings live in a byte-capped LRU (least recently used) cache, so the pages viewed longest ago are dropped first.
Fonts went from 144 MB to 9.2 MB
The font folder that comes with rhwp is 87 files and 144,327,972 bytes. The spike report called it "138 MB", which is the same number counted in mebibytes. The 222 documents actually used 17 of those files, about 37 MB.
The app ships 10 files, 9,207,952 bytes, about 6% of the original. Two rules decided what went in: a clear license and a close look. Hancom's own Hamchorom fonts were left out because Hancom's license page does not spell out whether they may be bundled in an app; Hamchorom Batang is drawn with Noto Serif KR and Hamchorom Dotum with NanumGothic, both under the SIL Open Font License. rhwp's NanumGothic was a subset that kept the reserved font name, so we swapped in the original TTF from google/fonts.

On 2026-10-05 we measured the cost on the same S21: how much first-page ink overlap (F1) against the reference drops with the substitute fonts. The pass mark, fixed in advance, was a median drop of 0.02 or less; the median came out at 0.0071. One file went over at 0.0336, a college entrance exam (Suneung) paper whose title is in Chinese characters (hanja). The difference sat in the hanja title and the circled numbers ① to ⑤, which the bundled fonts lack, so the system font draws them.
What the AI got wrong, and what verification changed
An AI coding agent (Claude) session ran the engine spike and wrote its report. Two days later, the follow-up experiments split the work: one agent measured, a separate verifier agent reopened the evidence files and recomputed every number, and only corrected values went into the docs. The first report's statistics were recounted at that point.
| First report | After verification |
|---|---|
| 24 real government documents | 17 korea.kr files (14 press releases) plus 7 others: 4 byte-identical to samples, 3 rhwp test fixtures |
| Samples: 177 HWP, 21 HWPX | 180 HWP, 18 HWPX (9 of them HWP 3.0) |
| Number recall around 0.9 | A bug in the comparison script: text runs were joined with no separator, so 11:00 and 10. 2. became 11:0010. 2.. Fixed, all 17 korea.kr files score 1.0 (a lenient upper bound) |
| Bundled fonts 9,700 KB (the follow-up's measuring agent) | KiB written as KB; 9,933,636 bytes is 9.93 MB (later cut to 9,207,952 bytes) |
"24 of 24 government documents" reads well, and 7 of the 24 were not government documents. Counted alone, the 17 real files were faster (1.4 s median) and lighter (286 MB max). The engine decision did not change, but without the verifier we would have published a number with the wrong provenance.
Writing this note, we recomputed the medians once more from the raw s21b.json. The report's 1.5, 2.1 and 3.0 seconds came out exactly; the 366 MB run of the 384-page file turned up then. (The verification report also flagged that another script had overwritten one raw file, which must be regenerated before anyone quotes it.)
Still open
- Low-end phones. According to the development plan, the Firebase Test Lab low-end run has not happened yet, so we do not know how a 400 MB renderer behaves on a 3 to 4 GB phone.
- Hanja-heavy documents. The 0.0336 is only recorded, from a sample of two.
- Upgrading rhwp. It is pre-1.0, so the app pins 0.8.6 and every build checks that the engine files match the pinned copy. An upgrade will be re-measured on the same 222 files. The other pre-release checks are in What to check before shipping an AI-built Android app.
FAQ
Can rhwp be used in a commercial Android app?
Yes. rhwp is MIT-licensed, but the Rust crates compiled into its WASM (Apache-2.0, BSD and others) need their notices too. The fonts it ships carry their own licenses and need checking file by file. HWP Viewer SugarDoc bundles 10 font files with confirmed licenses, OFL and others, and leaves out Hamchorom.
Why does a WebView HWP viewer use so much memory?
Every rendered page stays in the DOM as SVG. A 384-page file took the renderer to 2.8 GB with all pages drawn and 255 MB with only the visible ones.
Does one engine open both HWP and HWPX?
Yes. rhwp 0.8.6 opens both, and 221 of the 222 mixed files here opened. The difference between the two formats is explained in HWP vs HWPX: what differs and how to open both. If an HWPX file from a chat app will not open on your phone, see How to open an HWPX or HWP file on Android.
This note is written from values SugarMount measured itself; an AI coding agent was used to draft it.
More AX notes
- Pre-gzipping Android assets, measured: zero APK savings, and .pack.gz became .pack with a FileNotFoundException
- A market:// link opens a store chooser on SKT-sold Samsung phones: set the Play package first
- A splash that never moved on: addOnCompleteListener(this) and onStop
- "6.7" < "6.11" is false: comparing Remote Config versions as strings froze content updates
- A reverse-construction generator and the gate behind 1,100 arrow-puzzle levels
- Daily users rose after the redesign while organic D1 retention fell from 15.2% to 11.2%