Skip to content

Refactor rendering pipeline and enhance PDF object handling#9

Merged
Addy-A merged 16 commits into
masterfrom
skia-rbv
May 26, 2026
Merged

Refactor rendering pipeline and enhance PDF object handling#9
Addy-A merged 16 commits into
masterfrom
skia-rbv

Conversation

@Addy-A
Copy link
Copy Markdown
Owner

@Addy-A Addy-A commented May 26, 2026

This pull request introduces several improvements and new features to the rbara-gui project, most notably adding a persistent PDF viewer process for better performance, enhancing code readability and maintainability, and updating some user-facing content. The most significant change is the implementation of a persistent rbv viewer process, which allows for efficient reuse and inter-process communication, reducing the overhead of spawning new processes for each PDF view request. Additionally, there are various code style and formatting improvements, as well as updates to user interface elements.

Persistent PDF Viewer Process:

  • Added a persistent rbv viewer process (open_in_viewer_persistent) that reuses a single process for multiple PDF view requests, communicating via stdin and only spawning a new process if the current one is not alive. This is managed by the new ViewerHandle and RbvHandle structs. [1] [2] [3] [4]

Code Style and Readability Improvements:

  • Refactored several functions to improve readability and maintainability, including reformatting multi-line statements, improving error handling, and clarifying logic in functions such as load_persisted_profiles, add_trim_box, split_pages, extract_pages, load_icc_profile, load_metadata, and stitch_pages. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]

User Interface and Content Updates:

  • Expanded and updated the list of quips in quips.js, including new humorous entries and switching to single quotes for consistency.

Configuration and Versioning:

  • Bumped the version of rbara-gui from 0.1.4 to 0.1.6 in Cargo.toml.
  • Updated .claude/settings.local.json to allow additional commands and file access patterns for development and debugging.

Addy-A added 16 commits May 22, 2026 13:40
Adds the reference document covering the planned rbv
rendering overhaul: wgpu → Skia migration, async/progressive-DPI window
startup, interactive features (object tree, hit testing, hover color,
wireframe, plate preview), and GPU rasterization research.

Includes verified findings on PdfPipeline Send + Sync status and the
per-call PDFium serialization pattern that makes Arc<PdfPipeline> safe
for the background render thread.
- Replaced `wgpu` with `skia-safe` and `softbuffer` for rendering.
- Removed the `texture.rs` module and integrated texture handling into the new `renderer.rs` module.
- Updated `Cargo.toml` to include `skia-safe` and `softbuffer`, and removed `wgpu` and `pollster`.
- Refactored `viewer.rs` to utilize the new rendering system and handle zoom and pan functionality.
- Added tests for the new rendering logic and zoom/pan calculations.
- Updated `RenderConfig` struct to derive `Clone` for better usability.
…r rendering

- Removed unused dependencies and packages from Cargo.lock.
- Updated Cargo.toml to include glutin and glutin-winit for OpenGL support.
- Refactored SkiaRenderer to utilize OpenGL context and surface for rendering.
- Implemented overlay drawing functionality in SkiaRenderer.
- Enhanced Viewer to manage overlays and integrate OpenGL context creation.
- Added tests for overlay functionality and coordinate conversion.
Add rustybara/src/objects/ module to the core crate, providing a
structured view of every painted element on a PDF page extracted
directly from the content stream via lopdf — no PDFium dependency.

New types:
- PdfColor        — per-object DeviceGray / DeviceRGB / DeviceCMYK value
- PathPoint       — MoveTo / LineTo / Curveto / Close path segment
- SubPath         — ordered sequence of PathPoints in local (pre-CTM) space
- ObjectKind      — Fill / Stroke / FillStroke / Text / Image / FormXObject
- PageObject      — bbox, CTM, kind, fill/stroke color, subpaths for one object
- ObjectTree      — all objects on a page in back-to-front paint order

New functions:
- build_object_tree(doc, page_id) — walks q/Q/cm, color ops (g/rg/k/G/RG/K),
  path construction (m/l/c/v/y/h/re), all paint ops (S/s/f/B/b/n),
  Do (Image + Form XObject), and BT/ET text blocks; one PageObject per
  painted element with accurate page-space bbox
- hit_test(tree, x, y)             — returns objects at a PDF page coordinate
- point_in_path_nonzero(subpaths)  — nonzero winding rule on CTM-transformed
  polygon vertices; Bézier endpoints used as conservative approximation

Supporting addition:
- Rect::contains_point(x, y) — half-open [left,right) × [bottom,top)
  interval test; needed by hit_test bbox pre-filter

Reuses existing crate primitives throughout:
- crate::geometry::{Matrix, Rect} for all geometry and CTM operations
- crate::pages::boxes::object_to_f64 for numeric operand extraction
- Matrix::concat / transform_point / transform_rect for page-space mapping
- Introduced a debug log with a maximum capacity to track recent actions.
- Added functionality to sample pixel color from the current image on selection click.
- Implemented coordinate conversion from screen space to PDF space.
- Enhanced selection logic to prioritize the smallest bounding box for hit-testing.
- Added debug overlay to display viewport information and selected object details.
- Improved user interaction by distinguishing between click and drag actions.
- Updated key bindings for toggling overlays, wireframe, and debug mode.
…stic purposes

feat(tests): add tests for wireframe PDF export to ensure correctness
refactor(renderer): simplify test imports and improve code clarity
chore(dependencies): add tempfile crate for temporary file handling in tests
chore(settings): update permissions for additional Bash commands
chore(gitignore): include skia-testing directory in .gitignore
- Implemented `font.rs` to extract embedded font binary data from PDF resource dictionaries.
- Created `mod.rs` to organize the outline extraction features, including font extraction, encoding resolution, path generation, and writing.
- Developed `paths.rs` for extracting glyph outlines from PDF page content streams, handling various text operators and transformations.
- Introduced `writer.rs` to serialize `PositionedGlyph` outlines into PDF path operator sequences, facilitating the creation of an "Outline Text" version of PDFs.
- Added tests for all new functionalities to ensure correctness and reliability.
- tree.rs: Replace flat font_size-based bbox with 4-corner AABB computed
  through the full text matrix (Tm) and CTM. This correctly handles scaled,
  rotated, and sheared text; visual font size is now derived from the Tm
  scale components rather than the raw Tf font size (which is 1 in InDesign
  exports). Improves accuracy from ~1pt-tall slivers to proper-sized boxes.
- tree.rs: Fix Td/TD/T* operators to use lm.transform_point() (matching
  paths.rs) instead of lm.concat(&translate), which ignored lm's
  rotation/scale for multi-line text positioning.
- tree.rs: Remove incorrect font_size=12 reset in BT handler — PDF spec
  states BT only resets the text matrix (Tm/Tlm), not text state.
- renderer.rs: Remove global have_glyphs suppression that caused all text
  bboxes to disappear when any glyph outline existed. Text bboxes and glyph
  outline paths are now drawn independently.
- outline/font.rs: Add wrap_cff_in_otf() — synthesize a minimal OTTO
  OpenType header around raw Type1C CFF bytes so ttf_parser can parse them.
- outline/encoding.rs: Add glyph_id_for_char() helper falling back to
  glyph_index_by_name() via the Adobe Glyph List when glyph_index() fails
  (fonts without a cmap table). Add char_to_adobe_glyph_name() covering
  ASCII, Latin-1, and common typographic characters.
…EADME

ICC color readout:
- Add pixel_cmyk: Option<[f32; 4]> to ColorPanel for ICC-converted CMYK values.
- Add rustybara-icc (bundled-profiles) dependency to rbv.
- Add build_icc_transform() in viewer.rs: scans the OS ICC system for an sRGB
  profile (Windows System32/spool/drivers/color, macOS ColorSync, Linux
  /usr/share/color/icc) via IccProfile::from_user_bytes(); falls back to bundled
  AdobeRGB1998 when no system sRGB is found. Destination profile is US Web
  Coated SWOP (RelativeColorimetric intent).
- Transform is built lazily on first selection click and cached in
  Viewer::icc_transform for all subsequent clicks (no per-click construction).
- Color panel expanded from 2 rows (64px) to 3 rows (82px, 300px wide):
    Row 1 — sampled pixel RGBA
    Row 2 — PDF object fill/stroke color from content stream
    Row 3 — ICC CMYK estimate as integer percentages (C:XX% M:XX% Y:XX% K:XX%)

Zoom/pan-aware sampling crosshair:
- Add sampling_pdf_pos: Option<(f64, f64)> to Viewer; stores the selection
  click in PDF page coordinates (stable across zoom and pan changes).
- Each RedrawRequested projects sampling_pdf_pos to screen via compute_page_rect()
  + media_box math before taking the mutable state borrow.
- Add sample_marker: Option<[f32; 2]> parameter to SkiaRenderer::draw() so the
  caller supplies pre-projected screen coordinates.
- Add draw_sample_marker(): two-ring crosshair (white halo + orange-red accent,
  6px circle, 8–16px tick lines); drawn before the color panel so the panel text
  sits on top. Marker disappears when clicking outside the page.

docs(rbv):
- Add rbv/README.md covering: naming rationale and raster-first philosophy,
  architecture diagram, source file responsibilities, dependency stack (including
  pdfium runtime note), coordinate systems and conversion helpers, per-frame
  rendering order, wireframe mode object table, hit-test selection logic, color
  panel row-by-row explanation, sampling crosshair PDF-coord architecture,
  file watching behavior, all keyboard shortcuts, debug overlay contents, CLI
  usage with examples, known limitations, and contributing guide.
Add PdfColor::Separation { name, tint } variant to capture named
separation (spot color) inks in the object tree.

- Remove Copy from PdfColor (String field in Separation precludes it);
  add .clone() in commit_paint and fix .or() calls in viewer/renderer
- Add ColorSpace enum to GraphicsState (fill_cs, stroke_cs) tracking
  the active colorspace set by cs/CS operators
- Handle cs/CS: resolve colorspace by name from /Resources/ColorSpace,
  detecting Separation arrays to extract the ink name
- Handle scn/sc (fill) and SCN/SC (stroke): produce the correct
  PdfColor variant from the active ColorSpace via color_from_cs
- Add colorspace_dict_for helper, mirroring xobject_dict_for pattern
- Add Separation arm to color readout in viewer debug lines and
  renderer color panel ("Spot(InkName @ 0.750)" / "PdfColor Spot: ...")
- Add pdf_color_eq_separation unit test
Parse the `gs` content-stream operator to capture OP, op, and OPM
overprint flags from /Resources/ExtGState entries.

- Add OverprintState { stroke_overprint, fill_overprint, overprint_mode }
  — Copy + Default, lives in tree.rs alongside the other graphics-state
  public types
- Add overprint: OverprintState field to GraphicsState (default all-off)
- Handle `gs` operator in parse_content: calls read_ext_gstate which
  navigates resource_parent_id → /Resources/ExtGState → name → dict,
  then reads OP (bool), op (bool), OPM (int) — missing keys stay at default
- Stamp gs.overprint onto every emitted PageObject (paths, text, images,
  form placeholders) so callers can inspect overprint intent per object
- Add ext_gstate_dict_for helper, consistent with xobject_dict_for and
  colorspace_dict_for pattern
- Update downstream PageObject literals in hittest tests and export.rs
  to supply overprint: OverprintState::default()
- Add overprint_state_default_is_all_off and overprint_state_equality
  unit tests
- Update build_object_tree operator coverage table (cs/CS, scn/SCN rows
  were missing from item 3 — added in this pass)
- rbv/src/viewer.rs: add IpcCmd enum (Open, Page, Quit); extend
  ViewerEvent with IpcCommand variant; spawn stdin-reader thread in
  run() when --listen is set; handle IpcCommand in user_event with
  watcher reattachment on Open and event_loop.exit() on Quit; rename
  _watcher field to watcher for mutable access

- rbv/src/main.rs: add --listen CLI flag (default false); pass listen
  bool to viewer::run; add listen_flag tests

- rbara-gui/src/commands.rs: add RbvHandle, ViewerHandle types;
  add open_in_viewer_persistent command with dead-process detection
  and respawn; reuse existing process via stdin IPC if alive

- rbara-gui/src/lib.rs: manage ViewerHandle state; register
  open_in_viewer_persistent in invoke_handler
- Updated quips in the frontend to include new entries and improved formatting.
- Added egui and egui-winit dependencies for enhanced UI capabilities.
- Introduced a new ui_state module to manage viewer UI state, including plate selection and spot name extraction.
- Enhanced the SkiaRenderer to support egui texture updates and rendering.
- Implemented a side panel in the viewer for prepress tools, allowing users to filter by ink plates and view object properties.
- Improved event handling to integrate egui input with existing viewer interactions.
Copilot AI review requested due to automatic review settings May 26, 2026 22:52
@Addy-A Addy-A merged commit 1e9b438 into master May 26, 2026
1 of 2 checks passed
@Addy-A Addy-A review requested due to automatic review settings May 26, 2026 23:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant