Repository navigation
Release 2026.44.5 - #915
Merged
Merged
Conversation
The thin rotate arrows were hard to read at 14px. They now use a thicker arc with a large filled arrowhead and fill the 16px icon slot, for both the page rotate and view rotate buttons.
…ce streams Rectangles and ellipses saved with a dashed, dotted or other non-solid line style stored the pattern in /BS /D, but their appearance stream (/AP /N) stroked the outline without a dash operator. Other PDF readers draw the appearance, so these shapes showed solid lines there. Dashed and dotted rectangles and ellipses now look dashed in other PDF readers too. The appearance now writes the same pattern as /BS /D (streepOperator, the helper the polygon, ink, text box and callout appearances already use), for the outline and for the cross, as the screen draws them. The pattern is set after the hatch fill, which stays solid as on screen. Solid shapes get no dash operator. The wipeout shape shares this appearance and follows its own /BS /D the same way. Tests: a new unit test generates the rectangle and ellipse appearance for every line style (empty, filled, with cross, without border, invisible area, with hatch) and checks the dash operator against /BS /D; the line style round-trip test now also checks the appearance of rectangles and ellipses after saving, reopening and saving again.
Saved watermark definitions are stored as one JSON string in the PDF catalog. pdf-lib's decodeText() passes every decoded code point as a separate function argument, so a definition with a large embedded image exceeded the engine's argument limit (the limit differs per platform). Reading then failed silently and all watermarks disappeared from the Watermark dialog after reopening the file, even though the burned-in content was still there. The definitions are now decoded with TextDecoder for UTF-16 (BE and LE, selected by the byte order mark) and with PDFDocEncoding in bounded chunks for legacy strings. The stored format and the drawing of watermarks are unchanged. Regression tests save and reload a 400,000-character image definition with Unicode text, and legacy PDFDocEncoding and UTF-16LE strings. Review fixes: - None; version bump hunks left out.
The Watermark dialog only showed the chosen image; where the watermark would land on the page was only visible after adding it. The dialog now shows a live preview of a page of the open PDF next to the settings. - Text, font, size or auto-fit, colour, opacity, rotation, image, scale, position, page range and layer update the preview immediately. It uses the same placement and drawing functions as the screen and the saved file, so centre, corner and custom positions, rotation and auto-fit per page size match the result. - Previous/next buttons show other pages, with their own (rotated) size; the auto-fit size and the Custom X/Y prefill follow the previewed page. - Dragging the watermark in the preview switches the position to Custom and fills in X/Y. Ctrl+wheel zooms the preview, the middle mouse button pans it. - The dialog no longer blocks the document behind it. Switching documents or replacing the PDF closes it. - When an OPS watermark that is already in the file is edited, its stream is removed only from a private copy for the preview. Cancel leaves the document, its bytes and the undo history unchanged; Apply uses the existing add/update path. Review fixes: - Escape in the document behind the non-modal dialog (cancelling a tool or selection) no longer closes the dialog; Escape still closes it when the dialog has focus or was clicked last (dialog-escape.js, with tests). - Dragging keeps the watermark centre on the page instead of letting it be dragged out of sight; an image that has not loaded yet cannot be dragged as an invisible box (with tests). - Regression test that the hit test follows the clockwise rotation of the renderer (the 90 degree case could not tell the direction). - The preview of an edited in-file watermark falls back to reading the file when the byte cache is empty, as the apply path does, instead of showing a load error; the private pdf.js document uses the same safe options as the loader (no eval). - Layers switched off in the document stay off in the preview. - No JSON copy of the whole watermark (including large image data) on every keystroke just to track changes. - Rendered page canvases are released on page change and on close. - The preview background uses an existing theme colour (dark theme). - Test list entry without a stray blank line; version bump hunks left out.
A selected area measurement can now be reshaped without dragging nodes: - Right-click on an edge offers "Insert vertex here", which adds a vertex at the cursor, projected onto the edge. Right-click on a vertex offers "Delete vertex". - Double-click on an edge adds a vertex at the middle of that edge, as the issue asks; double-click on a vertex removes it. This works on the outer contour and on holes. Every ring keeps at least three vertices, and arc segments are left to the existing contour editing, so no curve changes silently. The area value and its label update at once, each edit is one undo step, and the hit reach is 8 screen pixels at every zoom level and view rotation. Locked annotations, locked layers, hidden annotations, read-only documents and other pages are refused. Perimeter and polyline measurements are not covered by this change. Review fixes: - Removing a corner now also refreshes the cached box of the area (x/y/width/height), as a node drag does. Loaded areas carry that box; it places the rotate grip and is the rotation centre, so it went stale. - One hit reach (AREA_VERTEX_HIT_PX) for the context menu, the double-click and the select tool; the context menu used a smaller reach, so a click that kept the selection could miss the edge in the menu. - The "Delete vertex" item gets the delete icon, like the polygon menu. - New round-trip test with the real saver and loader: after inserting and removing vertices (outer ring and hole) on /Rotate 0, 90, 180 and 270, the /Vertices, /OPS_Holes, the appearance stream and the reopened model hold the same vertices and the same area. It also checks that one edit is one undo step and that redo restores points and label. - Unit tests for the box refresh and for the zoom-independent hit reach. - The browser e2e script no longer writes a screenshot to a fixed path.
…#826) The own pivot point from 2026.44.0 (images, stamps and signatures) now also works on rectangles, masks, ellipses, area highlights, polygons and clouds. The crosshair sits at the centre by default; drag it (with object snap) to any point, also outside the shape. The rotation handle then rotates around it and the edge and corner handles keep it at the same place on the page. Double-click resets it to the centre. The pivot stays a field of the annotation (undo, copy and paste keep it) and is not written to the PDF, so it is back at the centre after reopening. While a shape's pivot is at the centre, the centre move grip makes way for it (the shape still moves by its body or border, and Ctrl+drag on the crosshair still copies); once the pivot is moved, the move grip returns. Review fixes: - Scaling around a moved pivot now keeps the dragged handle under the pointer; before, it moved only part of the way (half, for a centred pivot), so a handle could not be put on a snap point. - Image size snapping is skipped while scaling around a pivot; its guides belonged to the unshifted box. - Rotating and scaling around the pivot shift through applyMove, so a polygon's own vertices move along with its box. - Shift with angle snap rotates in steps around the pivot, as the normal rotation handle does; grabbing exactly on the pivot no longer jumps. - Escape during a pivot drag removes a pivot that only appeared in that drag (Object.assign kept the new field). - Cropping an image keeps the pivot on the same point of the page, and the crop snapshot (Escape, undo) restores it. - A pivot exactly on another handle stays grabbable and is drawn on top. - No crosshair on locked annotations, on another program's count polygon, in a multi-selection, or by default on a shape that is tiny on screen (it would cover the shape and block moving it). - Locked annotations can no longer be rotated or get a pivot through the pivot path.
) Poster printing absorbs ISO and point rounding with a small allowance per tile, so an A1 on borderless A3 at 100 % is 2 x 2 and an A0 on borderless A4 is 4 x 4. The few tenths of a millimetre that fall off the outer edges were never shown to the user. The print dialog now has "Crop small outer edges", on by default, with the largest crop of the current print next to it. Turning it off keeps every millimetre of the page on paper, at the cost of extra sheets (A1 on A3 becomes 3 x 3 again). The choice applies to the current print only and is on again when the dialog reopens. Labels are translated in all 40 locales. Review fixes: - Keep the per-tile rounding allowance from main as the default instead of replacing it with an opt-in fixed 0.75 mm bound; the opt-in default brought back the 3 x 3 (A1 on A3) and 5 x 5 (A0 on A4) of #855. - rasterLangs keeps its signature and default; randAfsnijden false is the strict full-coverage grid. The existing #855 tests stay unchanged. - The hint shows the actual largest crop of the print (posterRandAfsnijding, computed as if the option were on) instead of a fixed maximum, which was wrong for grids of more than two tiles. - Format the hint number with the locale decimal separator (toonGetal). - Tests for the default, the strict mode, full edge coverage over scales, orientations, overlap and cut marks, the per-axis crop bound and the reported crop; print = preview check for the strict mode. - Dropped the browser end-to-end script: it assumed the opt-in default.
Poster printing showed one sheet at a time, so checking the overall layout meant paging through every tile. The print dialog now shows an overview of the selected source page above the sheet preview: dashed tile boundaries and shaded overlap strips, computed from the same poster layout as the print. Clicking a tile, or Enter/Space on it, shows that sheet below; the sheet preview shades the strips that repeat on neighbouring sheets. The printed PDF is unchanged. Tile scale and overlap get integer step buttons. Every other locale-aware numeric field in the app shows hover/focus step buttons that send the field's own arrow-key step, so limits, fractional steps and change events stay as they were. Disabled and read-only fields and fields with their own buttons are skipped. New labels are translated in all 40 locales. Review fixes: - The overview memoizes its layout, page, markup and colour inputs. The dialog hands them over through the selected-sheet accessor, so every tile selection rebuilt the tile elements (losing keyboard focus after Enter) and re-rendered the overview image. - Focusing a hovered numeric field, including through a step click, no longer hides and re-shows its floating buttons. - Unit tests for the floating step buttons (hover, click, focus moving, skipped fields, covered and removed fields) with a stand-in document, and a source check for the overview memos; the new labels join the poster locale check. - Dropped the browser end-to-end script; it is not part of the unit suite.
In the web build the Fullscreen button turned on even when the browser refused full screen, and it could not be turned off again: every next click asked again, failed again and left the button on. That happens for example when the app runs inside a page whose iframe does not allow full screen. Ctrl+L behaved the same way. The button now shows the actual state of the window after every request, in the browser and on the desktop. When the browser or the embedding page refuses full screen, the app says so and points to the browser's own full-screen option, instead of doing nothing. Leaving full screen with Esc or the browser UI turns the button off as before. Review fixes: - The browser helper now reports whether a request was accepted; a refusal, a missing API or a page that does not allow full screen (document.fullscreenEnabled false) is no longer treated as success. - Explain a refused request in the web build with a translated message (view.fullscreenUnavailable, all 40 locales); no message on the desktop or in a headless test instance. - Support Safari's prefixed Fullscreen API (webkitRequestFullscreen, webkitFullscreenElement, webkitfullscreenchange). - Re-read the state shortly after an accepted request that has not taken effect yet (animated macOS transition), and after window resizes, so a window-manager change also updates the button; without this the stricter read-back could leave the button off while the window went full screen. - Esc clears a stale button state even when the window is not full screen. - Unit test js/ui/chrome/fullscreen.test.mjs covers refused, repeated, not-allowed and missing requests, enter/leave, a refused exit, the fullscreenchange event, the webkit prefix, desktop success/failure, a delayed native transition, headless and the translations. - The browser e2e script closes the new message between steps and also removes the prefixed API when it simulates a browser without one.
The Layer dropdown on the Format tab only ever listed "None" and did nothing. It is now the same layer choice as Properties > General: it lists the layers of the Markup Layers panel and the layers of the drawing, shows the layer of the selected markup (or "Mixed" for a selection on different layers), and moves the selection to the chosen layer in one undo step. The list follows new and renamed layers and the active document. The field is disabled without a selection, while drawing, and when a selected markup is locked. Review fixes: - The selection's layer is computed by a pure helper, selectieLaagKeuze() in annotations/laag-keuze.js, that reads the document's own annotations, so the ribbon does not show a stale layer when the selection holds another object than the document (moving and undo work on the document's annotations). - A long layer name can no longer widen the ribbon (max width on #fmt-layer). - Unit tests for the helper (empty, single, mixed, drawing layer, stale selection copy) and for the ribbon wiring in laag-keuze.test.mjs.
The Wall tool could only be started from the NL IFC Bouw category of the tool palette, which is hidden when the palette country is not Nederland. The Drawing tab now has a Wall button next to Line and Polyline. It works for every palette country and starts the same wall tool as the palette with the standard wall (100 mm brick): click start and end, keep clicking to continue the chain, Esc or right-click to stop. Corners and T-joins, thickness, material and the join options in Properties work as for palette walls. The palette entry is unchanged and keeps its own material and thickness. Like every ribbon button, Wall can get a keyboard shortcut in Preferences > Keyboard Shortcuts, and its tooltip then shows it; the name uses the existing translated "Wall" label in all 40 languages. Review fixes: - Unit test js/solid/components/ribbon/wand-knop.test.mjs: the button's place next to Line and Polyline, its reset of palette overrides, a wall from the button equal to the palette's standard wall (thickness, material, IfcWall, colour), the assignable shortcut shown in the tooltip, and the label in every locale.
- Side views show the hex head and nut square onto a flat: three faces (middle face e/2), facet lines and the true 30 degree chamfer curves; the head is chamfered on top, the nut on both ends. - Washers follow ISO 7089 (outer diameter and thickness per size). - Shank: solid outline, plain shank plus threaded length per ISO 4014 (b = 2d + 6 / 2d + 12 / 2d + 25), thin continuous minor-diameter lines, a thick thread-end line and a 45 degree chamfered tip; thin dash-dot axis. - Nut top view: hexagon, chamfer circle, thick minor circle and thin three-quarter major circle (ISO 6410); bolt-head plan view: hexagon, chamfer circle and optional washer ring. - Side-view heights use max(across corners, washer diameter); params, defaults, snap points and BOUT_MATEN keys are unchanged. - End plate and base plate connections reuse the same nut, washer and thread drawing. - Unit tests for sizes, view extents, drawn extent vs realSizeMm and snap points.
- One style for all 43 icons: viewBox 64, content within about 6..58, main stroke 2, detail stroke 1.25, text at least 11 units and at most one short label; tiny and clipped labels removed. - Steel sections get root radii and use the theme colour; brick, timber, concrete and insulation keep their material colours and hatches. - The bolt icon now shows the hex head, washer and threaded shank at the same optical size as the other icons. - Pile type 1 (narrow) and type 2 (wide) get their own icons with the type number, so they are distinguishable and no longer share one SVG. - Pattern and clip ids are prefixed and unique across the category. - The 16x16 category cube gets a symmetric top face. - Unit test guards the viewBox, text size, stroke weights and unique ids.
New parametric template "Anker in beton" (id anker) in the NL IFC Bouw palette, drawn with the same building blocks as the bolt: - cast-in anchor bolt with nut and washer, anchor plate, L-hook or J-hook; - chemical anchor: threaded rod in a drilled hole (d + 2 / d + 4) with mortar and a 118 degree drill point; - wedge anchor: thread, neck, cone and expansion clip in a drilled hole; - headed stud under a plate cast flush, with weld collar and head. Side view is a section: hatched concrete with the anchor or hole left open, surface line, fixture plate with clearance hole, ISO 7089 washer and chamfered hex nut on top. A plan view shows washer, nut and the rod end (ISO 6410), or the headed stud. Parameters: type, size M8-M24, embedment depth hef (default per type and size), plate thickness, protrusion (auto when 0), hook length, concrete hatch on/off and scale. realSizeMm equals the drawn extent; snap points add the anchor axis at the concrete surface. IFC: IfcMechanicalFastener. The palette gets a matching 48px icon; the bolt entry is now "Bout". Unit tests cover defaults, all variants and sizes, drawn extent, parts and snap points.
This was referenced Oct 31, 2026
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.
Open PDF Studio 2026.44.5
Merge with "Create a merge commit" (not squash or rebase), so each contributor's commit and authorship stays in the history.
Each reviewed pull request is included as one squashed commit with its original author. Problems found in review were fixed on top, with regression tests, inside the same commit; each commit message lists those fixes.
New
Live watermark preview (feat: Live watermerkvoorbeeld met verslepen en paginanavigatie (#848) #871, thanks @oscar981-op): the watermark dialog shows the page with the watermark, which you can drag into place, and you can browse the pages. Review fixes:
Edit the vertices of area measurements (feat: Hoekpunten van oppervlaktemetingen direct bewerken (#872) #874, thanks @oscar981-op):
Review fixes: the bounding box (rotation handle) updates after deleting a vertex, and the hit distance is the same 8 screen pixels everywhere. A new save round trip test covers all page rotations.
Own pivot point for shapes (feat: versleepbaar draaipunt voor afbeeldingen en vormen (#826) #828, thanks @oscar981-op): the pivot point from 2026.44.0 now also works on rectangles, masks, ellipses, highlights, polygons and clouds. Scaling keeps the dragged handle under the pointer. The PR's separate pivot implementation was folded into the existing one. Review fixes:
Poster overview and step buttons (feat(print): selecteerbaar posteroverzicht en numerieke stapknoppen (#853) #866, thanks @oscar981-op): a selectable overview of all poster sheets above the preview, and step buttons on number fields. Review fixes: selecting a tile no longer rebuilds the overview or loses keyboard focus, the step buttons no longer flicker, and the step buttons got unit tests.
Wall button on the Drawing tab (feat: Wand-gereedschap op tabblad Tekenen (#864) #870, thanks @oscar981-op): draw walls from the Drawing tab whatever the palette country. Review fix: a regression test for the button and its default wall.
Bolts, nuts and anchors drawn properly: bolt heads and nuts show the hexagon facets with chamfer arcs; washers follow ISO 7089; the shaft shows a plain shank, thread with thin core lines and a chamfered tip; the nut top view shows the thread convention. A new "Anchor in concrete" tool draws cast-in anchor bolts (nut, anchor plate, L-hook, J-hook), chemical anchors, wedge anchors and headed studs, in side view in hatched concrete and in plan view.
Cleaner NL IFC Bouw palette icons: all icons share one style (margins, line weights, size), with no tiny or clipped text; the two pile types have their own icons.
Larger rotate icons: the rotate left/right icons in the ribbon are larger and easier to read.
Fixed
Fixes #848
Fixes #872
Fixes #826
Fixes #853
Fixes #864
Fixes #873
Fixes #865
Verification