summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDan Allen <dan.j.allen@gmail.com>2022-08-22 23:55:07 -0600
committerGitHub <noreply@github.com>2022-08-22 23:55:07 -0600
commitb23e24937eb0d75eabdf17d91a59e9acc871e4b7 (patch)
treef051522e4a95cab735d37103094b16b8b5a3516d /lib
parent0abb4a012c1750081330fda1395526246093f100 (diff)
share image info cache between primary and scratch documents to avoid decoding same image more than once (PR #2321)
Diffstat (limited to 'lib')
-rw-r--r--lib/asciidoctor/pdf/converter.rb2
-rw-r--r--lib/asciidoctor/pdf/ext/prawn/images.rb27
2 files changed, 29 insertions, 0 deletions
diff --git a/lib/asciidoctor/pdf/converter.rb b/lib/asciidoctor/pdf/converter.rb
index 576c8682..f00441f0 100644
--- a/lib/asciidoctor/pdf/converter.rb
+++ b/lib/asciidoctor/pdf/converter.rb
@@ -432,6 +432,7 @@ module Asciidoctor
else
@optimize = nil
end
+ image_info_cache
# allocate_scratch_prototype calls create_scrate_prototype to set up the scratch prototype
# scratch calls init_scratch on a copy of the prototype to instantiate a scratch document
# push_scratch and pop_scratch make changes to the document catalog and attributes transactional
@@ -5212,6 +5213,7 @@ module Asciidoctor
# NOTE: prepare scratch document to use page margin from recto side (which has same width as verso side)
set_page_margin page_margin_recto
end
+ @image_info_cache = originator.instance_variable_get :@image_info_cache
@scratch_prototype = originator.instance_variable_get :@scratch_prototype
@tmp_files = originator.instance_variable_get :@tmp_files
text_formatter.scratch = true
diff --git a/lib/asciidoctor/pdf/ext/prawn/images.rb b/lib/asciidoctor/pdf/ext/prawn/images.rb
index 7f85d431..414ae4e9 100644
--- a/lib/asciidoctor/pdf/ext/prawn/images.rb
+++ b/lib/asciidoctor/pdf/ext/prawn/images.rb
@@ -33,9 +33,36 @@ module Asciidoctor
end
end
+ # Override built-in method to cache info separately from obj.
+ def build_image_object file
+ if ::File === file
+ cache_key = ((::File.absolute_path? (file_path = file.path)) ? file_path : (File.absolute_path file_path)).to_sym
+ info = image_info_cache[cache_key]
+ end
+ unless info
+ image_content = verify_and_read_image file
+ if cache_key || !(info = image_info_cache[(cache_key = ::Digest::SHA1.hexdigest image_content)])
+ # build the image object
+ info = (::Prawn.image_handler.find image_content).new image_content
+ renderer.min_version info.min_pdf_version if info.respond_to? :min_pdf_version
+ image_info_cache[cache_key] = info
+ end
+ end
+ # reuse image if it has already been embedded
+ unless (image_obj = image_registry[cache_key])
+ # add the image to the PDF then register it in case we see it again
+ image_registry[cache_key] = image_obj = info.build_pdf_object self
+ end
+ [image_obj, info]
+ end
+
def recommend_prawn_gmagick? err, image_format
::Prawn::Errors::UnsupportedImageType === err && !(defined? ::GMagick::Image) && ((err.message.include? 'PNG') || (%w(jpg png).none? image_format))
end
+
+ def image_info_cache
+ @image_info_cache ||= {}
+ end
end
::Prawn::Document.extensions << Images