Class: Pdfrb::Model::Cos::Dictionary
- Extended by:
- ArlingtonBacked
- Defined in:
- lib/pdfrb/model/cos/dictionary.rb
Overview
Common Object Syntax dictionary (s7.3.7). Wraps a Hash of Symbol -> PDF value. Subclassed by every semantic Type::*.
Field metadata can come from two sources (mutually exclusive per field; last declaration wins):
* `define_field` — hand-coded (HexaPDF shape).
* `arlington_object "Name"` — auto-loaded from vendored TSVs
via Pdfrb::Arlington::Loader. Calls `define_field` under
the hood with types translated to Ruby classes.
Direct Known Subclasses
Stream, Type::AFEmbeddedFileParameter, Type::AFFileSpecEF, Type::Action, Type::ActionSound, Type::AddActionCatalog, Type::AddActionFormField, Type::AddActionPageObject, Type::AddActionScreenAnnotation, Type::AddActionWidgetAnnotation, Type::AlternateImage, Type::Annotation, Type::AnnotationProjectionDict, Type::Appearance, Type::AppearanceCharacteristics, Type::AppearancePrinterMarkDict, Type::AppearanceSubDict, Type::AppearanceTrapNet, Type::AppearanceTrapNetSubDict, Type::AppleSupplementalText, Type::AuthCode, Type::Bead, Type::BorderEffect, Type::BorderStyle, Type::BorderStyling, Type::BoxColorInfo, Type::BoxStyle, Type::CCITTFaxDecodeParms, Type::CIDFontDescriptorMetrics, Type::CIDSystemInfo, Type::CalGray, Type::CalRGB, Type::Catalog, Type::CertSeedValue, Type::CharProcMap, Type::ClassMap, Type::Collection, Type::CollectionColors, Type::CollectionField, Type::CollectionFolder, Type::CollectionItem, Type::CollectionSchema, Type::CollectionSort, Type::CollectionSplit, Type::CollectionSubitem, Type::ColorSpaceMap, Type::ColorantsDict, Type::CryptDecodeParms, Type::CryptFilter, Type::CryptFilterMap, Type::CryptFilterPublicKey, Type::CryptFilterPublicKeyMap, Type::DCTDecodeParms, Type::DPMMetadataStream, Type::DPart, Type::DPartRoot, Type::Data, Type::DestOutputProfile, Type::DestinationDict, Type::DestsMap, Type::DevExtensions, Type::DeviceN, Type::DeviceNMixingHints, Type::DeviceNProcess, Type::DictionaryOfDictionaries, Type::DictionaryOfFunctions, Type::DocMDPTransformParameters, Type::DocTimeStamp, Type::DocumentSecurityStore, Type::Dss, Type::EmbeddedFileParameter, Type::EncryptedPayload, Type::EncryptionPublicKey, Type::EncryptionStandard, Type::ExData3DMarkup, Type::ExDataMarkupGeo, Type::ExDataProjection, Type::Extensions, Type::FDDict, Type::Field, Type::FieldMDPTransformParameters, Type::FileSpecEF, Type::FileSpecRF, Type::FileSpecification, Type::FileTrailer, Type::FixedPrint, Type::FlateDecodeParms, Type::FloatingWindowParameters, Type::Font, Type::FontDescriptor, Type::FontEncoding, Type::Function, Type::GTSProcStepsGroup, Type::GeographicCoordinateSystem, Type::GeospatialMeasure, Type::GraphicsStateParameter, Type::GraphicsStateParameterMap, Type::GroupAttributes, Type::Halftone, Type::IconFit, Type::Info, Type::InteractiveForm, Type::InteriorColor, Type::JBIG2DecodeParms, Type::Lab, Type::LegalAttestation, Type::LineEndingStyling, Type::LinearizationParameterDict, Type::MDPDict, Type::Mac, Type::MarkInformation, Type::MarkedContentReference, Type::Measure, Type::MediaClipDataMHBE, Type::MediaClipSectionMHBE, Type::MediaCriteria, Type::MediaDuration, Type::MediaOffsetFrame, Type::MediaOffsetMarker, Type::MediaOffsetTime, Type::MediaPermissions, Type::MediaPlayParameters, Type::MediaPlayParametersMH, Type::MediaPlayerInfo, Type::MediaPlayers, Type::MediaScreenParameters, Type::MediaScreenParametersMHBE, Type::MicrosoftWindowsLaunchParam, Type::MinimumBitDepth, Type::MinimumScreenSize, Type::Movie, Type::MovieActivation, Type::Names, Type::Namespace, Type::NavNode, Type::Navigator, Type::NumberFormat, Type::OPIVersion13Dict, Type::OPIVersion20Dict, Type::ObjectReference, Type::OptContentCreatorInfo, Type::OptContentExport, Type::OptContentLanguage, Type::OptContentPageElement, Type::OptContentPrint, Type::OptContentUsage, Type::OptContentUsageApplication, Type::OptContentUser, Type::OptContentView, Type::OptContentZoom, Type::OptionalContentConfiguration, Type::OptionalContentGroup, Type::OptionalContentMembership, Type::OptionalContentProperties, Type::Outline, Type::OutlineItem, Type::OutputIntent, Type::OutputIntentsContainer, Type::Page, Type::PageLabel, Type::PagePieceInfo, Type::PageTreeNode, Type::PaperMetaData, Type::Pattern, Type::PatternMap, Type::Permissions, Type::PointData, Type::PrinterMarkSubDict, Type::ProjectedCoordinateSystem, Type::Projection, Type::Rendition, Type::RenditionBE, Type::RenditionMH, Type::RequirementsHandler, Type::Resources, Type::RichMediaActivation, Type::RichMediaAnimation, Type::RichMediaCommand, Type::RichMediaConfiguration, Type::RichMediaContent, Type::RichMediaCuePoint, Type::RichMediaDeactivation, Type::RichMediaHeight, Type::RichMediaInstance, Type::RichMediaParams, Type::RichMediaPosition, Type::RichMediaPresentation, Type::RichMediaSettings, Type::RichMediaWidth, Type::RichMediaWindow, Type::RoleMap, Type::RoleMapNS, Type::Separation, Type::Shading, Type::ShadingMap, Type::SigFieldLock, Type::SigFieldSeedValue, Type::Signature, Type::SignatureBuildDataAppDict, Type::SignatureBuildDataDict, Type::SignatureBuildDataSigQDict, Type::SignatureBuildPropDict, Type::SignatureReferenceDocMDP, Type::SignatureReferenceFieldMDP, Type::SignatureReferenceIdentity, Type::SignatureReferenceUR, Type::SlideShow, Type::SoftMaskAlpha, Type::SoftMaskLuminosity, Type::SoftwareIdentifier, Type::Solidities, Type::SourceInformation, Type::SpectralData, Type::StreamDict, Type::StructElem, Type::StructTreeRoot, Type::StructureAttributes, Type::StructureElementKid, Type::StructureReference, Type::StyleDict, Type::SubjectDN, Type::Target, Type::Thread, Type::ThreeDActivation, Type::ThreeDAnimationStyle, Type::ThreeDBackground, Type::ThreeDCrossSection, Type::ThreeDLightingScheme, Type::ThreeDMeasure, Type::ThreeDNode, Type::ThreeDReference, Type::ThreeDRenderMode, Type::ThreeDUnits, Type::ThreeDView, Type::ThreeDViewAddEntries, Type::TimeStampDict, Type::Timespan, Type::Transition, Type::TrapRegion, Type::URIDict, Type::URLAlias, Type::URTransformParameters, Type::UniversalDictionary, Type::UserProperty, Type::VRIMap, Type::ViewParams, Type::ViewerPreferences, Type::Viewport, Type::Vri, Type::WebCaptureCommand, Type::WebCaptureCommandSettings, Type::WebCaptureInfo, Type::XObjectMap
Instance Attribute Summary
Attributes inherited from Object
Class Method Summary collapse
-
.apply_arlington_definition(definition) ⇒ Object
Merge the TSV's field definitions into the class's field set (ArlingtonBacked#arlington_object hook).
- .arlington_default(field_def) ⇒ Object
- .arlington_key_to_symbol(key) ⇒ Object
- .arlington_one_type_to_ruby(t) ⇒ Object
- .arlington_required?(field_def) ⇒ Boolean
-
.arlington_scalar(token) ⇒ Object
TSV default cells are raw strings; convert per scalar shape so typed access returns Integer/Symbol/etc.
- .arlington_types_to_ruby(field_def) ⇒ Object
- .arlington_version(field_def) ⇒ Object
-
.define_field(pdf_name, type:, required: false, default: nil, indirect: nil, allowed_values: nil, version: "1.0", arlington: nil) ⇒ Object
Declare a field on this class.
-
.define_field_from_arlington(field_def) ⇒ Object
Merge Arlington field metadata with any hand-coded define_field declaration.
-
.each_field ⇒ Object
Iterate (name, Field) pairs across the inheritance chain.
-
.field(name) ⇒ Object
Look up a field by name; walks the inheritance chain.
- .lookup_type(symbol) ⇒ Object
- .merged_field(existing, field_def) ⇒ Object
- .own_fields ⇒ Object
- .register_type(symbol, klass = self) ⇒ Object
-
.type_map ⇒ Object
/Type-symbol -> Dictionary subclass.
Instance Method Summary collapse
-
#[](name) ⇒ Object
Typed access.
- #[]=(name, value) ⇒ Object
- #delete(name) ⇒ Object
-
#each ⇒ Object
Iterate (Symbol, processed-value) pairs.
-
#each_raw ⇒ Object
Iterate (Symbol, raw-value) pairs without accessor pipeline.
- #empty? ⇒ Boolean
-
#initialize(value = {}, oid: 0, gen: 0, document: nil) ⇒ Dictionary
constructor
A new instance of Dictionary.
- #key?(name) ⇒ Boolean
- #keys ⇒ Object
- #pdf_type ⇒ Object
-
#validate ⇒ Object
Walk every declared field and yield (message, correctable) for each violation.
Methods included from ArlingtonBacked
Methods inherited from Object
#==, define_type, #deref, #indirect?, #must_be_indirect?, pdf_type
Constructor Details
#initialize(value = {}, oid: 0, gen: 0, document: nil) ⇒ Dictionary
Returns a new instance of Dictionary.
204 205 206 207 208 209 210 211 212 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 204 def initialize(value = {}, oid: 0, gen: 0, document: nil) value ||= {} unless value.is_a?(::Hash) raise ArgumentError, "Dictionary value must be a Hash, got #{value.class}" end super(value, oid: oid, gen: gen, document: document) apply_required_defaults end |
Class Method Details
.apply_arlington_definition(definition) ⇒ Object
Merge the TSV's field definitions into the class's field set (ArlingtonBacked#arlington_object hook).
78 79 80 81 82 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 78 def apply_arlington_definition(definition) definition.each_field do |field_def| define_field_from_arlington(field_def) end end |
.arlington_default(field_def) ⇒ Object
168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 168 def arlington_default(field_def) raw = field_def.default_value return nil if raw.nil? return raw unless raw.is_a?(::String) if raw.start_with?("[") && raw.end_with?("]") return raw[1..-2].split.then { |tokens| tokens.map { |t| arlington_scalar(t) } } end scalar = arlington_scalar(raw) return scalar.to_sym if scalar.is_a?(::String) && field_def.types_raw.include?("name") scalar end |
.arlington_key_to_symbol(key) ⇒ Object
158 159 160 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 158 def arlington_key_to_symbol(key) key.to_sym end |
.arlington_one_type_to_ruby(t) ⇒ Object
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 137 def arlington_one_type_to_ruby(t) case t when :boolean then [TrueClass, FalseClass] when :integer then Integer when :number then [Integer, Float] when :name then Symbol when :string, :"string-ascii", :"string-text" then String when :"string-byte" then Fields::PDFByteString when :array then Pdfrb::Model::PdfArray when :dictionary then Pdfrb::Model::Cos::Dictionary when :stream then Pdfrb::Model::Cos::Stream when :null then NilClass when :date then Fields::PDFDate when :rectangle then Pdfrb::Model::Rectangle when :matrix then Pdfrb::Model::Matrix when :bitmask then Integer when :"name-tree", :"number-tree" then Pdfrb::Model::Cos::Dictionary end end |
.arlington_required?(field_def) ⇒ Boolean
163 164 165 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 163 def arlington_required?(field_def) field_def.required_literal == true end |
.arlington_scalar(token) ⇒ Object
TSV default cells are raw strings; convert per scalar shape so typed access returns Integer/Symbol/etc.
186 187 188 189 190 191 192 193 194 195 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 186 def arlington_scalar(token) case token when "true" then true when "false" then false when "null" then nil when /\A-?\d+\z/ then Integer(token, 10) when /\A-?\d+\.\d+\z/ then Float(token) else token end end |
.arlington_types_to_ruby(field_def) ⇒ Object
132 133 134 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 132 def arlington_types_to_ruby(field_def) field_def.types.map { |t| arlington_one_type_to_ruby(t) }.flatten.compact.uniq end |
.arlington_version(field_def) ⇒ Object
198 199 200 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 198 def arlington_version(field_def) field_def.since_version.to_s end |
.define_field(pdf_name, type:, required: false, default: nil, indirect: nil, allowed_values: nil, version: "1.0", arlington: nil) ⇒ Object
Declare a field on this class. Mirrors HexaPDF's
define_field shape; we add an arlington: slot for the
source FieldDefinition.
46 47 48 49 50 51 52 53 54 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 46 def define_field(pdf_name, type:, required: false, default: nil, indirect: nil, allowed_values: nil, version: "1.0", arlington: nil) own_fields[pdf_name] = Fields::Field.new( pdf_name, type: type, required: required, default: default, indirect: indirect, allowed_values: allowed_values, version: version, arlington: arlington ) end |
.define_field_from_arlington(field_def) ⇒ Object
Merge Arlington field metadata with any hand-coded define_field declaration. Hand-coded fields win: if the class already declares this key explicitly (with a type), we rebuild the Field preserving the hand-coded type/default/required and only attach the Arlington def for reference.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 96 def define_field_from_arlington(field_def) types = arlington_types_to_ruby(field_def) return if types.empty? key = arlington_key_to_symbol(field_def.key) existing = own_fields[key] if existing own_fields[key] = merged_field(existing, field_def) return end define_field( key, type: types.length == 1 ? types.first : types, required: arlington_required?(field_def), default: arlington_default(field_def), version: arlington_version(field_def), arlington: field_def ) end |
.each_field ⇒ Object
Iterate (name, Field) pairs across the inheritance chain. A subclass field with the same name shadows (replaces) the inherited one entirely.
67 68 69 70 71 72 73 74 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 67 def each_field return enum_for(:each_field) unless block_given? if superclass <= Pdfrb::Model::Cos::Dictionary superclass.each_field { |n, f| yield n, f unless own_fields.key?(n) } end own_fields.each { |n, f| yield n, f } end |
.field(name) ⇒ Object
Look up a field by name; walks the inheritance chain.
57 58 59 60 61 62 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 57 def field(name) return own_fields[name] if own_fields.key?(name) return superclass.field(name) if superclass <= Pdfrb::Model::Cos::Dictionary nil end |
.lookup_type(symbol) ⇒ Object
39 40 41 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 39 def lookup_type(symbol) TYPE_MAP[symbol] end |
.merged_field(existing, field_def) ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 118 def merged_field(existing, field_def) Fields::Field.new( existing.pdf_name, type: existing.type, required: existing.required, default: existing.default, indirect: existing.indirect, allowed_values: existing.allowed_values, version: arlington_version(field_def), arlington: field_def ) end |
.own_fields ⇒ Object
85 86 87 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 85 def own_fields @own_fields ||= {} end |
.register_type(symbol, klass = self) ⇒ Object
34 35 36 37 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 34 def register_type(symbol, klass = self) TYPE_MAP[symbol] = klass klass.define_type(symbol) unless klass.pdf_type end |
.type_map ⇒ Object
/Type-symbol -> Dictionary subclass. Populated by
register_type. Used by Document#wrap to dispatch.
30 31 32 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 30 def type_map TYPE_MAP end |
Instance Method Details
#[](name) ⇒ Object
Typed access. Resolves References, wraps in field-specific subclass, applies default, runs converters.
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 216 def [](name) name = name.to_sym unless name.is_a?(::Symbol) field = self.class.field(name) data = @value[name] data = field.default if data.nil? && field&.default? return nil if data.nil? data = dereference(data) data = data.value if unbox_object?(data) return data unless field converted = Fields.apply(field, data, document) if converted @value[name] = converted converted else data end end |
#[]=(name, value) ⇒ Object
237 238 239 240 241 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 237 def []=(name, value) raise ArgumentError, "Dictionary keys must be Symbols" unless name.is_a?(::Symbol) @value[name] = value end |
#delete(name) ⇒ Object
248 249 250 251 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 248 def delete(name) name = name.to_sym unless name.is_a?(::Symbol) @value.delete(name) end |
#each ⇒ Object
Iterate (Symbol, processed-value) pairs. Slower than #each_raw because it runs the full accessor pipeline; use that when you don't need wrapping.
256 257 258 259 260 261 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 256 def each return enum_for(:each) unless block_given? @value.each_key { |k| yield(k, self[k]) } self end |
#each_raw ⇒ Object
Iterate (Symbol, raw-value) pairs without accessor pipeline.
264 265 266 267 268 269 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 264 def each_raw return enum_for(:each_raw) unless block_given? @value.each { |k, v| yield(k, v) } self end |
#empty? ⇒ Boolean
272 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 272 def empty?; @value.empty?; end |
#key?(name) ⇒ Boolean
243 244 245 246 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 243 def key?(name) name = name.to_sym unless name.is_a?(::Symbol) !@value[name].nil? end |
#keys ⇒ Object
271 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 271 def keys; @value.keys; end |
#pdf_type ⇒ Object
274 275 276 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 274 def pdf_type self.class.pdf_type || self[:Type] end |
#validate ⇒ Object
Walk every declared field and yield (message, correctable) for each violation. Returns an Enumerator if no block given.
280 281 282 283 284 285 286 |
# File 'lib/pdfrb/model/cos/dictionary.rb', line 280 def validate return enum_for(:validate) unless block_given? self.class.each_field do |name, field| validate_one(name, field) { |*a| yield(*a) } end end |