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