Feature: Circular magnifying glass - #1
Open
starlit-void wants to merge 18 commits into
Open
Conversation
Update Simplified Chinese language pack
In single-page mode Viewer::grabMagnifiedRegion built the magnified image with a device pixel ratio of devicePixelRatioF() in the out-of-bounds branch, while the in-bounds branch returns a DPR-1 image and the source crop is itself DPR 1. A QPainter draws in logical coordinates, so painting the DPR-1 crop onto a DPR-2 (Retina) image scaled the content up by the ratio and clipped it. Because this only happens once the sampled region touches the page edge, magnification jumped discontinuously near the left/right edges and edge detail was pushed off the loupe. Keep the out-of-bounds image at DPR 1 so both branches produce the same scale.
…tive With the magnifying glass active, moving the cursor to the bottom of the page hit the goToFlow page-selection hover zone. The bar did not visibly appear, but the hover handling took over the mouse events there, so the magnifying glass stopped following the cursor and could not reach the bottom of the page. Skip the bottom hover zone while the magnifying glass is shown.
…improvements Magnifying glass improvements (macOS)
Only image based epubs, this is experimental.
Update Simplified Chinese language pack
Update Chinese translations in yacreader_zh_CN.ts
Update Chinese translations in yacreaderlibrary_zh_CN.ts
starlit-void
force-pushed
the
feature/circular-magnifying-glass
branch
from
July 29, 2026 11:05
4d6d547 to
5415ea0
Compare
Introduce an optional circular loupe for the magnifying glass, toggled from the Options window (General tab). The circle's diameter is the wider of the two configured rectangle dimensions, derived at display time only: the rectangle size setting (MAG_GLASS_SIZE) is never overwritten, so switching modes restores the exact saved size. MagnifyingGlass now separates its logical rectangle (the source of truth for size gestures and the persisted setting) from its display geometry, which grows to a max(w, h) square while circular. The shape is realised with a widget mask for corner transparency plus a custom paintEvent for antialiased interior scaling. A secondary bezel-ring option (default on, enabled only when circular is active) draws an antialiased filled annulus inset just inside the mask so its outer edge forms a smooth silhouette that blends into the page, hiding the aliased mask edge.
The loupe's sampled content is pushed outward toward the viewport edges so edge content is reachable without moving the cursor all the way to the edge, while tracking the cursor 1:1 in the middle. - Viewer::easeViewerPos normalizes the cursor about the viewport center (the region the page is actually drawn in — the top-level window would fold in the toolbar/chrome and ease too hard), runs it through a smoothstep ramp, and scales it by the loupe half-extent. The half-size cap keeps the cursor's point inside the loupe view and ties the strength to loupe size: a minimum loupe is nearly linear, a large one eases hard. Rectangular loupes cap per axis; circular loupes cap the displacement vector radially. - Two tuning knobs: edgeReach saturates the ramp before the cursor reaches the border, and edgeStrength scales the peak push below the half-extent. - Per-axis letterbox gate: easing only helps where there is off-page content to bring toward the cursor, so it is skipped on an axis once the page is letterboxed by more than minLetterboxFraction (10%) of its own size there. Overflow, an exact fit, or a thin margin still ease, so the effect does not vanish the instant a page is a hair smaller than the viewport. In continuous view the horizontal extent is the page under the cursor, so the gate can vary per row. - Only the content is eased; the loupe widget follows the cursor, so the zoomed image swims a little toward the edge inside the loupe. - MouseHandler's mouse-move path routes through updateImage so both update paths share the eased positioning. - New MAG_GLASS_EDGE_EASE config (default on) with an Options toggle, applied live via Viewer::updateConfig().
… delta) Resizing the magnifying glass by scrolling used to step on the mere sign of each wheel event, so a trackpad's many tiny high-resolution events each fired a full step and the faintest two-finger brush resized the loupe. Accumulate the active gesture's signed angleDelta and only take a step once the running total crosses a 120-unit threshold (looping so a fast multi-notch event still steps several times). A real mouse wheel delivers 120 per notch in one event, so it still steps once per notch; the 120 threshold is itself the trackpad/mouse discriminator, so no device-type branching is needed. The accumulator resets when the gesture changes (different modifier) or after ~400ms idle so a stale partial gesture can't leak forward. Applies to the size, height (Ctrl), width (Alt), and zoom (Shift) branches.
The circle's diameter is the wider of the two logical dimensions, so squaring up a wide, short rectangle could exceed the parent on the other axis even though the rectangle itself fit: a logical 800x175 became an 800x800 widget, taller than the viewport it magnifies. The grow steps only ever clamped the logical rectangle, so nothing caught this. Clamp the circle's side to the same fraction of the parent that the grow steps enforce, taken on whichever axis is tighter. The logical size is untouched, so the saved setting and the rectangular mode are unaffected.
starlit-void
force-pushed
the
feature/circular-magnifying-glass
branch
from
July 29, 2026 11:14
5415ea0 to
eae6bba
Compare
It introduced a regression that causes the magnifying glass to start tiny because the size of the parent is not know when the magnifying glass is setup, and it would require to update the clamping for every resize of the parent widget. Clamping ads complexity and some UX inconsistencies that are not really necessary IMO.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds an option for a circular magnifying glass to the settings dialog. When selected, the largest dimension of the rectangular magnifier is used to determine the diameter of the circle. An additional optional dark ring can be added to the outside of the circular shape to improve how it is read on-screen.
Furthermore, added an additional easing option that helps the magnifier reach the edges of the page before the cursor actually hits the edge. This easing is only added when the edge of the page is close to the edge of the window (when there is enough background between the two, the problem isn't so bad). It's kind of necessary because lots of stuff happens at the edge of the window and it makes magnifying difficult.
Finally, I've also added some macOS-helping code to the scroll wheel (trackpad). Before, I would just barely touch the touchpad and the size of the magnifier would flicker up and down rapidly. Now you need to have more intent with your two-finger scrolling to make it change the size. This also makes the size change in smaller increments, which I feel is more smooth.