Class: Ucode::CodeChart::Verifier::ResvgStrategy
- Defined in:
- lib/ucode/code_chart/verifier/resvg_strategy.rb
Overview
Strategy backed by the resvg CLI (resvg --help). Preferred
over MutoolStrategy for accuracy and speed when available —
resvg is purpose-built for SVG rendering and produces
pixel-stable output across platforms.
Same byte-wise diff fallback as MutoolStrategy. PNG output
is normalized via resvg's --quantize 8 to reduce byte-level
noise across renderer versions.
Constant Summary
Constants inherited from Strategy
Instance Method Summary collapse
- #available? ⇒ Boolean
- #diff(png_a, png_b) ⇒ Object
-
#initialize(runner: Ucode::Glyphs::EmbeddedFonts::Mutool::SystemRunner.new) ⇒ ResvgStrategy
constructor
A new instance of ResvgStrategy.
- #render_pdf_region(pdf_path, page, _rect, png_path, scale: 2.0) ⇒ Object
- #render_svg(svg_path, png_path, scale: 2.0) ⇒ Object
- #write_diff_artifact(png_a, png_b, dest) ⇒ Object
Constructor Details
#initialize(runner: Ucode::Glyphs::EmbeddedFonts::Mutool::SystemRunner.new) ⇒ ResvgStrategy
Returns a new instance of ResvgStrategy.
20 21 22 23 |
# File 'lib/ucode/code_chart/verifier/resvg_strategy.rb', line 20 def initialize(runner: Ucode::Glyphs::EmbeddedFonts::Mutool::SystemRunner.new) super() @runner = runner end |
Instance Method Details
#available? ⇒ Boolean
25 26 27 |
# File 'lib/ucode/code_chart/verifier/resvg_strategy.rb', line 25 def available? system("which resvg >/dev/null 2>&1") end |
#diff(png_a, png_b) ⇒ Object
51 52 53 54 55 56 57 58 59 60 |
# File 'lib/ucode/code_chart/verifier/resvg_strategy.rb', line 51 def diff(png_a, png_b) bytes_a = File.binread(png_a) bytes_b = File.binread(png_b) return 100.0 if bytes_a.bytesize != bytes_b.bytesize same = bytes_a.each_byte.with_index.count do |byte, idx| byte == bytes_b.getbyte(idx) end (100.0 * (1.0 - same.to_f / bytes_a.bytesize)).round(2) end |
#render_pdf_region(pdf_path, page, _rect, png_path, scale: 2.0) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/ucode/code_chart/verifier/resvg_strategy.rb', line 37 def render_pdf_region(pdf_path, page, _rect, png_path, scale: 2.0) # resvg doesn't render PDFs; we rely on mutool to first # convert the page region to SVG, then resvg to PNG. Two # subprocess hops, but reuses each tool's strength. intermediate = Pathname.new("#{png_path}.svg") dpi = (72 * scale).round @runner.run("mutool", "draw", "-F", "svg", "-o", intermediate.to_s, "-r", dpi.to_s, pdf_path.to_s, page.to_s) @runner.run("resvg", "--quantize", "8", intermediate.to_s, png_path.to_s) FileUtils.rm_f(intermediate.to_s) Pathname.new(png_path) end |
#render_svg(svg_path, png_path, scale: 2.0) ⇒ Object
29 30 31 32 33 34 35 |
# File 'lib/ucode/code_chart/verifier/resvg_strategy.rb', line 29 def render_svg(svg_path, png_path, scale: 2.0) width = (1000 * scale).round @runner.run("resvg", "-w", width.to_s, "--quantize", "8", svg_path.to_s, png_path.to_s) Pathname.new(png_path) end |
#write_diff_artifact(png_a, png_b, dest) ⇒ Object
62 63 64 65 66 67 |
# File 'lib/ucode/code_chart/verifier/resvg_strategy.rb', line 62 def write_diff_artifact(png_a, png_b, dest) data_a = File.binread(png_a) data_b = File.binread(png_b) Pathname.new(dest).binwrite(data_a + data_b) Pathname.new(dest) end |