Two PDF pages overlapped on the screen. After another fix, they moved too far apart. Later, the pages looked better, but search highlights no longer lined up with the text.
I was building MihirakiPDFViewer, an iPad PDF reader for books I had scanned. I wanted to read them as two-page spreads, with an option to show the cover on its own. AI helped me write and revise the code, but deciding whether a fix actually worked took repeated use and more precise descriptions of the expected behavior.
In Part 1, I described the broader development process. This time, I want to focus on one deceptively small feature: putting two pages next to each other.
This is a development retrospective for beginners, rather than a complete PDF rendering tutorial. The diagrams below explain the layout problems; they are not screenshots from the original debugging sessions.
A layout fix needs a visible target
My early attempts produced overlapping pages, shifted pages, and unwanted space between them. Changing the layout could improve one symptom while leaving another behind.
A report that the code was fixed was useful as a starting point. I still needed to open the PDF and check the result.
The request became clearer when I separated three requirements:
- Preserve each page's aspect ratio.
- Keep both pages within the available reading area.
- Make their inner edges meet at the center of the spread.
Figure 1. The same viewport and page size can produce different spreads. The vertical line marks the center; the lower example places both inner edges on it.
The distinction between a page's container and its visible content mattered. A container can occupy half the screen while a page scaled to fit inside it is narrower. Centering the visible page inside that container can leave an unwanted gap near the spine.
Looking at page dimensions, scale, and position helped make the problem concrete. Asking to remove the gap was more useful when I could also say which edges should meet and which proportions should stay the same.
My main lesson was to describe the expected picture before requesting another layout change.
Right-to-left reading involves more than reversing things
Japanese books also made page order a separate problem. During development, a right-to-left configuration opened on the last page instead of the beginning.
I needed to distinguish three decisions:
- Which pages belong in the same spread?
- Which page appears on the left or right?
- Which spread appears first, and how does navigation move through the document?
These decisions are related, but reversing all of them together does not automatically produce the intended reading experience.
Here is a small example. The numbers are PDF file positions starting at 1, not printed page labels. Each bracket shows the screen from left to right:
- Left-to-right, no separate cover: [1 | 2] → [3 | 4] → [5]
- Right-to-left, no separate cover: [2 | 1] → [4 | 3] → [5]
- Right-to-left, cover alone: [1] → [3 | 2] → [5 | 4]
Figure 2. A five-page example with a separate cover and right-to-left reading. Downward arrows show the sequence of spreads, not the direction of a swipe gesture.
Eventually, page grouping was extracted into a helper, PDFPageGrouping, that works with arrays of page indices independently of PDFKit objects. That made the pairing rules easier to inspect and test separately from the view.
For a beginner, the useful idea is simple: write down a tiny example with numbered pages before working on the full reader. A five-page document makes the cover rule and left/right placement easier to discuss. Without a separate cover, page 5 is left unpaired. With the cover shown alone, as in Figure 2, the remaining four pages form two complete spreads.
Those examples still need to be checked in the actual interface. Correct groups alone do not prove that the initial selection or navigation behaves correctly.
Moving the page also affects search highlights
Another problem appeared when search found the right text but the highlight was drawn in the wrong place.
The page image was positioned according to its alignment in the spread, while the highlight calculation still assumed a centered page. Both calculations could look reasonable in isolation and still disagree on the screen.
The fix was to use the same page-origin calculation for both the image and its highlights. Here, the origin means the on-screen position of the page's top-left corner. The shared helper, alignedPageOriginX, supplies the horizontal part of that position.
Figure 3. Blue marks the page's left edge. In the upper example, the highlight uses a different horizontal origin, shown in orange. In the lower example, both use the same origin, so the highlight covers the text.
This was a useful reminder that a page and its overlays form one visual feature. After changing page placement, I needed to check search results as well as the page itself.
The broader lesson applies to image editors, document viewers, and other interfaces with annotations: when the underlying content moves or scales, check everything drawn on top of it.
What I would write before the next layout change
My expectations also changed through daily reading. For example, I initially asked for the pages to shrink when controls appeared. After using that behavior, I reconsidered the request. Some revisions came from discovering what felt better, rather than from a failure to implement the original instruction.
For the next change, I would start with a short description like this:
Open a five-page PDF containing searchable text in right-to-left spread mode, with the cover shown alone. The first view should show page 1. The next spread should show page 3 on the left and page 2 on the right. The pages should keep their proportions, fit within the reading area, and meet at the center. Search for a word on either page and confirm that its highlight stays aligned. Show and hide the controls, then check the page size and position again.
This gives me something observable to verify after an AI-assisted change. It also helps separate a bug from a requirement I have changed my mind about.
Two-page viewing taught me to be more specific about what I expected to see, to separate page grouping from navigation, and to check overlays whenever page geometry changed.
If you have built a reader or another interface with paired content, which assumption about ordering or positioning surprised you?
Source and code: Adapted and reorganized from my Japanese development notes on Qiita (first article, second article). The project is on GitHub.
AI disclosure: I used AI assistance to organize and draft this English article and to help create the explanatory diagrams. The development experiences described here are my own.




