Module: Arrolio::Renderer::Pdf::FontEmbedding
- Included in:
- Arrolio::Renderer::Pdf
- Defined in:
- lib/arrolio/renderer/pdf/font_embedding.rb
Overview
Extracted concern: Pdfrb coupling points kept out of the emission path.
Instance Method Summary collapse
- #attach_to_resources(font_name, ref) ⇒ Object
- #collect_codepoints(page, by_font) ⇒ Object
-
#prepare_embedded_fonts(pages) ⇒ Object
Pre-scan all pages, collect codepoints per font family, then call Font::Embedder for each font_path.
Instance Method Details
#attach_to_resources(font_name, ref) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/arrolio/renderer/pdf/font_embedding.rb', line 39 def attach_to_resources(font_name, ref) catalog = @document.catalog res = catalog.value[:Resources] Arrolio::Logger.debug "attach_to_resources: Resources=#{res.class}" unless res.is_a?(Hash) && res[:Font].is_a?(Hash) catalog.value[:Resources] = { Font: {} } end font_hash = catalog.value[:Resources][:Font] key = (format('EF%d', (font_hash.length + 1))).to_sym font_hash[key] = ref @embedded_resource_keys ||= {} @embedded_resource_keys[font_name] = key end |
#collect_codepoints(page, by_font) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/arrolio/renderer/pdf/font_embedding.rb', line 53 def collect_codepoints(page, by_font) (page.static_regions.values + page.regions.values).each do |region| region.placed_boxes.each do |box| next unless box.kind == :text next unless box.data.is_a?(Hash) && box.data[:lines] box.data[:lines].each do |line| next unless line.is_a?(TextLayout::Line) line.placed_runs.each do |pr| next unless pr.run.is_a?(InlineRun) # Collect under the RUN'S font name, not the # paragraph's. Italic/bold runs have different # font_names and need their own subsets. run_font = pr.run.style.font_name next unless @font_paths.key?(run_font) pr.run.text.each_codepoint { |cp| by_font[run_font] << cp } end end end end end |
#prepare_embedded_fonts(pages) ⇒ Object
Pre-scan all pages, collect codepoints per font family, then call Font::Embedder for each font_path.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/arrolio/renderer/pdf/font_embedding.rb', line 11 def (pages) return if @font_paths.empty? codepoints = Hash.new { |h, k| h[k] = [] } pages.each { |page| collect_codepoints(page, codepoints) } Arrolio::Logger.debug "collected codepoints for fonts: #{codepoints.keys.inspect}" @font_paths.each do |font_name, path| exists = File.exist?(path) has_cp = codepoints.key?(font_name) cp_count = codepoints[font_name]&.length || 0 Arrolio::Logger.debug "font #{font_name}: exists=#{exists} cp=#{cp_count}" next unless exists next unless has_cp cps = codepoints[font_name].uniq = Font::Embedder.new(@document, path, base_font_name: font_name) ref = .(cps) attach_to_resources(font_name, ref) @font_embedders[font_name] = @font_encoders[font_name] = Font::TextEncoder.new() @font_refs[font_name] = ref rescue StandardError => e Arrolio::Logger.warn "embed failed for #{font_name}: #{e.class}: #{e.[0,100]}" Arrolio::Logger.debug e.backtrace.first(5).join("\n") end end |