lib/hexapdf/document.rb in hexapdf-0.3.0 vs lib/hexapdf/document.rb in hexapdf-0.4.0
- old
+ new
@@ -133,10 +133,11 @@
else
@security_handler = nil
end
@listeners = {}
+ @cache = Hash.new {|h, k| h[k] = {} }
end
# :call-seq:
# doc.object(ref) -> obj or nil
# doc.object(oid) -> obj or nil
@@ -313,29 +314,28 @@
data.stream = stream if stream
if type.kind_of?(Class)
klass = type
else
- default = if data.stream
- HexaPDF::Stream
- elsif data.value.kind_of?(Hash)
- HexaPDF::Dictionary
- else
- HexaPDF::Object
- end
if data.value.kind_of?(Hash)
type ||= deref(data.value[:Type])
subtype ||= deref(data.value[:Subtype])
end
if subtype
- klass = GlobalConfiguration.constantize('object.subtype_map'.freeze, subtype)
+ klass = GlobalConfiguration.constantize('object.subtype_map'.freeze, subtype) { nil }
end
if type && !klass
- klass = GlobalConfiguration.constantize('object.type_map'.freeze, type)
+ klass = GlobalConfiguration.constantize('object.type_map'.freeze, type) { nil }
end
- klass ||= default
+ klass ||= if data.stream
+ HexaPDF::Stream
+ elsif data.value.kind_of?(Hash)
+ HexaPDF::Dictionary
+ else
+ HexaPDF::Object
+ end
end
klass.new(data, document: self)
end
@@ -414,9 +414,39 @@
end
# Dispatches the message +name+ with the given arguments to all registered listeners.
def dispatch_message(name, *args)
@listeners[name] && @listeners[name].each {|obj| obj.call(*args)}
+ end
+
+ # Caches the value or the return value of the given block using the given Object::PDFData and
+ # key arguments as composite hash key. If a cached value already exists, it is just returned.
+ #
+ # This facility can be used to cache expensive operations in PDF objects that are easy to
+ # compute again.
+ #
+ # Use #clear_cache to clear the cache if necessary.
+ def cache(pdf_data, key, value = nil)
+ @cache[pdf_data][key] ||= value || yield
+ end
+
+ # Returns +true+ if there is a value cached for the composite key consisting of the given
+ # +pdf_data+ and +key+ objects.
+ #
+ # Also see: #cache
+ def cached?(pdf_data, key)
+ @cache.key?(pdf_data) && @cache[pdf_data].key?(key)
+ end
+
+ # Clears all cached data or, if a Object::PDFData object is given, just the cache for this one
+ # object.
+ #
+ # It is *not* recommended to clear the whole cache! Better clear the cache for individual PDF
+ # objects!
+ #
+ # Also see: #cache
+ def clear_cache(pdf_data = nil)
+ pdf_data ? @cache[pdf_data].clear : @cache.clear
end
# Returns the Pages object that provides convenience methods for working with pages.
#
# Also see: HexaPDF::Type::PageTreeNode