pdfrb 0.2.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +24 -0
- data/Gemfile +1 -0
- data/PROPOSAL.canvas-clip.md +92 -0
- data/PROPOSAL.canvas-draw-image-matrix.md +87 -0
- data/PROPOSAL.canvas-rich-text.md +103 -0
- data/PROPOSAL.canvas-text-lines.md +77 -0
- data/PROPOSAL.canvas-transparency.md +106 -0
- data/PROPOSAL.external-font-metrics.md +129 -0
- data/PROPOSAL.font-embedding-fontfile2.md +88 -0
- data/PROPOSAL.font-resolver-ttc.md +105 -0
- data/PROPOSAL.font-resolver.md +96 -0
- data/PROPOSAL.font-subsetting.md +98 -0
- data/PROPOSAL.gradient-shadings.md +110 -0
- data/PROPOSAL.page-mediabox-setter.md +66 -0
- data/PROPOSAL.per-glyph-width.md +91 -0
- data/PROPOSAL.stringio-require.md +53 -0
- data/PROPOSAL.struct-tree-root.md +102 -0
- data/PROPOSAL.text-measurement.md +93 -0
- data/PROPOSAL.ttf-table-parsing-fix.md +112 -0
- data/RELEASE.md +48 -0
- data/lib/pdfrb/action/base.rb +21 -0
- data/lib/pdfrb/action/types.rb +178 -0
- data/lib/pdfrb/action.rb +55 -0
- data/lib/pdfrb/annotation/base.rb +79 -0
- data/lib/pdfrb/annotation/types.rb +222 -0
- data/lib/pdfrb/annotation.rb +78 -0
- data/lib/pdfrb/appearance/generator.rb +216 -0
- data/lib/pdfrb/appearance.rb +11 -0
- data/lib/pdfrb/arlington/object_definition.rb +2 -2
- data/lib/pdfrb/arlington/predicate/evaluator.rb +1 -1
- data/lib/pdfrb/arlington/predicate/functions.rb +25 -9
- data/lib/pdfrb/arlington/predicate.rb +1 -5
- data/lib/pdfrb/cli/batch.rb +18 -0
- data/lib/pdfrb/cli/debug_info.rb +18 -0
- data/lib/pdfrb/cli/files.rb +16 -0
- data/lib/pdfrb/cli/fonts.rb +16 -0
- data/lib/pdfrb/cli/form.rb +18 -0
- data/lib/pdfrb/cli/image2pdf.rb +18 -0
- data/lib/pdfrb/cli/images.rb +34 -0
- data/lib/pdfrb/cli/info.rb +20 -0
- data/lib/pdfrb/cli/inspect.rb +18 -0
- data/lib/pdfrb/cli/merge.rb +18 -0
- data/lib/pdfrb/cli/modify.rb +18 -0
- data/lib/pdfrb/cli/optimize.rb +18 -0
- data/lib/pdfrb/cli/split.rb +21 -0
- data/lib/pdfrb/cli/watermark.rb +18 -0
- data/lib/pdfrb/cli.rb +312 -7
- data/lib/pdfrb/color/color_space.rb +259 -0
- data/lib/pdfrb/color/icc_profile.rb +90 -0
- data/lib/pdfrb/color.rb +12 -0
- data/lib/pdfrb/compare/comparator.rb +244 -0
- data/lib/pdfrb/compare/report.rb +78 -0
- data/lib/pdfrb/compare.rb +42 -0
- data/lib/pdfrb/composer.rb +161 -0
- data/lib/pdfrb/conformance/pdf_a.rb +317 -56
- data/lib/pdfrb/conformance/pdf_ua.rb +186 -29
- data/lib/pdfrb/conformance/pdf_x.rb +247 -0
- data/lib/pdfrb/conformance/rule.rb +78 -0
- data/lib/pdfrb/conformance/structure_elements.rb +174 -0
- data/lib/pdfrb/conformance/verapdf_bridge.rb +92 -0
- data/lib/pdfrb/conformance.rb +7 -3
- data/lib/pdfrb/content/canvas.rb +217 -72
- data/lib/pdfrb/content/color_space.rb +157 -0
- data/lib/pdfrb/content/hidden_text_detector.rb +167 -0
- data/lib/pdfrb/content/operator.rb +21 -1
- data/lib/pdfrb/content/operators/clipping.rb +36 -0
- data/lib/pdfrb/content/operators/graphics_state_params.rb +15 -0
- data/lib/pdfrb/content/operators.rb +21 -0
- data/lib/pdfrb/content/shading/base.rb +139 -0
- data/lib/pdfrb/content/shading.rb +17 -0
- data/lib/pdfrb/content/smart_text_extractor.rb +85 -0
- data/lib/pdfrb/content/tiling_pattern.rb +78 -0
- data/lib/pdfrb/content/transformation_matrix.rb +61 -0
- data/lib/pdfrb/content.rb +7 -26
- data/lib/pdfrb/destination/fit.rb +185 -0
- data/lib/pdfrb/destination.rb +13 -0
- data/lib/pdfrb/digital_signature/cms_handler.rb +22 -0
- data/lib/pdfrb/digital_signature/signing.rb +107 -11
- data/lib/pdfrb/digital_signature/timestamp_handler.rb +45 -0
- data/lib/pdfrb/digital_signature/verification.rb +88 -9
- data/lib/pdfrb/digital_signature/verification_result.rb +14 -0
- data/lib/pdfrb/digital_signature.rb +26 -2
- data/lib/pdfrb/document/annotations.rb +120 -3
- data/lib/pdfrb/document/associated_files.rb +104 -0
- data/lib/pdfrb/document/colors.rb +95 -0
- data/lib/pdfrb/document/destinations.rb +127 -5
- data/lib/pdfrb/document/display.rb +84 -0
- data/lib/pdfrb/document/fonts.rb +417 -45
- data/lib/pdfrb/document/form.rb +338 -0
- data/lib/pdfrb/document/form_xobject.rb +68 -0
- data/lib/pdfrb/document/graphics_state.rb +91 -0
- data/lib/pdfrb/document/images.rb +4 -4
- data/lib/pdfrb/document/info.rb +102 -0
- data/lib/pdfrb/document/layers.rb +62 -0
- data/lib/pdfrb/document/metadata.rb +12 -5
- data/lib/pdfrb/document/output_intents.rb +91 -0
- data/lib/pdfrb/document/page_labels.rb +80 -0
- data/lib/pdfrb/document/pages.rb +68 -19
- data/lib/pdfrb/document/portfolio.rb +119 -0
- data/lib/pdfrb/document/shadings.rb +159 -0
- data/lib/pdfrb/document/stamps.rb +68 -0
- data/lib/pdfrb/document/structure.rb +242 -0
- data/lib/pdfrb/document.rb +73 -4
- data/lib/pdfrb/encryption/identity.rb +13 -0
- data/lib/pdfrb/encryption/password_verification.rb +53 -8
- data/lib/pdfrb/encryption/security_handler.rb +8 -5
- data/lib/pdfrb/encryption/standard_security_handler.rb +154 -81
- data/lib/pdfrb/encryption.rb +17 -0
- data/lib/pdfrb/error.rb +2 -2
- data/lib/pdfrb/filter/brotli_decode.rb +32 -0
- data/lib/pdfrb/filter/ccitt_fax_decode.rb +12 -0
- data/lib/pdfrb/filter/crypt.rb +2 -2
- data/lib/pdfrb/filter/dct_decode.rb +18 -0
- data/lib/pdfrb/filter/flate_decode.rb +4 -18
- data/lib/pdfrb/filter/jbig2_decode.rb +12 -0
- data/lib/pdfrb/filter/jpx_decode.rb +18 -0
- data/lib/pdfrb/filter/lzw_decode.rb +3 -2
- data/lib/pdfrb/filter/png_predictor.rb +94 -0
- data/lib/pdfrb/filter.rb +26 -13
- data/lib/pdfrb/font/afm_parser.rb +50 -26
- data/lib/pdfrb/font/cmap/writer.rb +9 -0
- data/lib/pdfrb/font/encoding/win_ansi_encoding.rb +17 -0
- data/lib/pdfrb/font/encoding.rb +32 -3
- data/lib/pdfrb/font/metrics_helper.rb +121 -0
- data/lib/pdfrb/font/true_type/file.rb +10 -1
- data/lib/pdfrb/font/true_type/glyf.rb +82 -0
- data/lib/pdfrb/font/true_type/kern.rb +58 -0
- data/lib/pdfrb/font/true_type/loca.rb +42 -0
- data/lib/pdfrb/font/true_type/maxp.rb +44 -0
- data/lib/pdfrb/font/true_type/name.rb +53 -0
- data/lib/pdfrb/font/true_type/post.rb +93 -0
- data/lib/pdfrb/font/true_type/subsetter.rb +3 -5
- data/lib/pdfrb/font/true_type/wrapper.rb +102 -0
- data/lib/pdfrb/font/true_type.rb +7 -0
- data/lib/pdfrb/font.rb +2 -0
- data/lib/pdfrb/font_loader/from_configuration.rb +19 -0
- data/lib/pdfrb/font_loader/from_file.rb +20 -0
- data/lib/pdfrb/font_loader/standard14.rb +20 -0
- data/lib/pdfrb/font_loader/variant_from_name.rb +36 -0
- data/lib/pdfrb/font_loader.rb +4 -0
- data/lib/pdfrb/font_resolver.rb +138 -0
- data/lib/pdfrb/image/audit.rb +94 -0
- data/lib/pdfrb/image/downsampler.rb +124 -0
- data/lib/pdfrb/image.rb +13 -0
- data/lib/pdfrb/image_loader/jpeg.rb +39 -58
- data/lib/pdfrb/image_loader/png.rb +31 -257
- data/lib/pdfrb/layout/bidi.rb +198 -0
- data/lib/pdfrb/layout/box.rb +49 -0
- data/lib/pdfrb/layout/box_fitter.rb +54 -0
- data/lib/pdfrb/layout/column_box.rb +71 -0
- data/lib/pdfrb/layout/container_box.rb +45 -0
- data/lib/pdfrb/layout/frame.rb +67 -0
- data/lib/pdfrb/layout/image_box.rb +44 -0
- data/lib/pdfrb/layout/inline_box.rb +25 -0
- data/lib/pdfrb/layout/line.rb +55 -0
- data/lib/pdfrb/layout/list_box.rb +87 -0
- data/lib/pdfrb/layout/numeric_refinements.rb +43 -0
- data/lib/pdfrb/layout/page_style.rb +65 -0
- data/lib/pdfrb/layout/style.rb +62 -0
- data/lib/pdfrb/layout/table_box.rb +66 -0
- data/lib/pdfrb/layout/text_box.rb +38 -0
- data/lib/pdfrb/layout/text_fragment.rb +45 -0
- data/lib/pdfrb/layout/text_layouter.rb +123 -0
- data/lib/pdfrb/layout.rb +28 -0
- data/lib/pdfrb/linearization/hint_stream.rb +93 -0
- data/lib/pdfrb/linearization/writer.rb +259 -0
- data/lib/pdfrb/linearization.rb +21 -0
- data/lib/pdfrb/model/cos/dictionary.rb +12 -0
- data/lib/pdfrb/model/pdf_array.rb +2 -2
- data/lib/pdfrb/model/type/action.rb +42 -0
- data/lib/pdfrb/model/type/action_go_to_3d_view.rb +14 -0
- data/lib/pdfrb/model/type/action_go_to_dp.rb +16 -0
- data/lib/pdfrb/model/type/action_go_to_r.rb +26 -0
- data/lib/pdfrb/model/type/action_goto.rb +34 -0
- data/lib/pdfrb/model/type/action_hide.rb +26 -0
- data/lib/pdfrb/model/type/action_import_data.rb +18 -0
- data/lib/pdfrb/model/type/action_java_script.rb +18 -0
- data/lib/pdfrb/model/type/action_launch.rb +22 -0
- data/lib/pdfrb/model/type/action_movie.rb +22 -0
- data/lib/pdfrb/model/type/action_named.rb +23 -0
- data/lib/pdfrb/model/type/action_nop.rb +12 -0
- data/lib/pdfrb/model/type/action_rendition.rb +28 -0
- data/lib/pdfrb/model/type/action_reset_form.rb +22 -0
- data/lib/pdfrb/model/type/action_rich_media_execute.rb +17 -0
- data/lib/pdfrb/model/type/action_set_ocg_state.rb +32 -0
- data/lib/pdfrb/model/type/action_set_state.rb +14 -0
- data/lib/pdfrb/model/type/action_sound_action.rb +23 -0
- data/lib/pdfrb/model/type/action_submit_form.rb +64 -0
- data/lib/pdfrb/model/type/action_thread.rb +23 -0
- data/lib/pdfrb/model/type/action_trans.rb +30 -0
- data/lib/pdfrb/model/type/action_uri.rb +30 -0
- data/lib/pdfrb/model/type/af_embedded_file.rb +11 -0
- data/lib/pdfrb/model/type/af_file_specification.rb +34 -0
- data/lib/pdfrb/model/type/annotation.rb +49 -10
- data/lib/pdfrb/model/type/appearance.rb +41 -0
- data/lib/pdfrb/model/type/appearance_characteristics.rb +36 -0
- data/lib/pdfrb/model/type/appearance_generator.rb +22 -0
- data/lib/pdfrb/model/type/appearance_trap_net.rb +84 -0
- data/lib/pdfrb/model/type/border_effect.rb +25 -0
- data/lib/pdfrb/model/type/border_styling.rb +38 -0
- data/lib/pdfrb/model/type/box_color_info.rb +21 -0
- data/lib/pdfrb/model/type/box_style.rb +19 -0
- data/lib/pdfrb/model/type/button.rb +17 -0
- data/lib/pdfrb/model/type/cal_gray.rb +17 -0
- data/lib/pdfrb/model/type/cal_rgb.rb +22 -0
- data/lib/pdfrb/model/type/caret_annotation.rb +21 -0
- data/lib/pdfrb/model/type/catalog.rb +99 -16
- data/lib/pdfrb/model/type/choice.rb +21 -0
- data/lib/pdfrb/model/type/cid_font.rb +52 -1
- data/lib/pdfrb/model/type/cid_font_descriptor_metrics.rb +28 -0
- data/lib/pdfrb/model/type/cid_system_info.rb +28 -0
- data/lib/pdfrb/model/type/circle_annotation.rb +20 -0
- data/lib/pdfrb/model/type/collection.rb +27 -0
- data/lib/pdfrb/model/type/collection_field.rb +24 -0
- data/lib/pdfrb/model/type/collection_item.rb +19 -0
- data/lib/pdfrb/model/type/collection_schema.rb +25 -0
- data/lib/pdfrb/model/type/collection_sort.rb +13 -0
- data/lib/pdfrb/model/type/crypt_filter.rb +58 -0
- data/lib/pdfrb/model/type/device_n.rb +37 -0
- data/lib/pdfrb/model/type/device_n_mixing_hints.rb +17 -0
- data/lib/pdfrb/model/type/device_n_process.rb +13 -0
- data/lib/pdfrb/model/type/doc_mdp_transform_parameters.rb +21 -0
- data/lib/pdfrb/model/type/document_security_store.rb +55 -0
- data/lib/pdfrb/model/type/embedded_file.rb +19 -0
- data/lib/pdfrb/model/type/embedded_file_parameter.rb +48 -0
- data/lib/pdfrb/model/type/encryption_public_key.rb +38 -0
- data/lib/pdfrb/model/type/encryption_standard.rb +68 -0
- data/lib/pdfrb/model/type/field_mdp_transform_parameters.rb +26 -0
- data/lib/pdfrb/model/type/file_attachment_annotation.rb +29 -0
- data/lib/pdfrb/model/type/file_spec_ef.rb +22 -0
- data/lib/pdfrb/model/type/file_spec_rf.rb +21 -0
- data/lib/pdfrb/model/type/file_specification.rb +43 -0
- data/lib/pdfrb/model/type/file_trailer.rb +54 -0
- data/lib/pdfrb/model/type/font.rb +73 -2
- data/lib/pdfrb/model/type/font_cid_type0.rb +17 -0
- data/lib/pdfrb/model/type/font_cid_type2.rb +17 -0
- data/lib/pdfrb/model/type/font_descriptor.rb +47 -0
- data/lib/pdfrb/model/type/font_descriptor_cid_type0.rb +15 -0
- data/lib/pdfrb/model/type/font_descriptor_cid_type2.rb +15 -0
- data/lib/pdfrb/model/type/font_encoding.rb +47 -0
- data/lib/pdfrb/model/type/font_file.rb +28 -0
- data/lib/pdfrb/model/type/font_file2.rb +32 -0
- data/lib/pdfrb/model/type/font_file3.rb +23 -0
- data/lib/pdfrb/model/type/font_multiple_master.rb +60 -0
- data/lib/pdfrb/model/type/font_true_type.rb +1 -1
- data/lib/pdfrb/model/type/font_type0.rb +1 -1
- data/lib/pdfrb/model/type/font_type1.rb +1 -1
- data/lib/pdfrb/model/type/font_type3.rb +1 -1
- data/lib/pdfrb/model/type/form_field.rb +73 -0
- data/lib/pdfrb/model/type/free_text_annotation.rb +37 -0
- data/lib/pdfrb/model/type/function.rb +42 -0
- data/lib/pdfrb/model/type/function_exponential.rb +31 -0
- data/lib/pdfrb/model/type/function_postscript.rb +25 -0
- data/lib/pdfrb/model/type/function_sampled.rb +55 -0
- data/lib/pdfrb/model/type/function_stitching.rb +33 -0
- data/lib/pdfrb/model/type/generic_appearance.rb +40 -0
- data/lib/pdfrb/model/type/graphics_state_parameter.rb +69 -0
- data/lib/pdfrb/model/type/halftone.rb +21 -0
- data/lib/pdfrb/model/type/halftone_type1.rb +17 -0
- data/lib/pdfrb/model/type/halftone_type10.rb +16 -0
- data/lib/pdfrb/model/type/halftone_type16.rb +11 -0
- data/lib/pdfrb/model/type/halftone_type5.rb +24 -0
- data/lib/pdfrb/model/type/halftone_type6.rb +16 -0
- data/lib/pdfrb/model/type/highlight_annotation.rb +11 -0
- data/lib/pdfrb/model/type/icc_based_color_space.rb +24 -0
- data/lib/pdfrb/model/type/icon_fit.rb +31 -0
- data/lib/pdfrb/model/type/indexed.rb +32 -0
- data/lib/pdfrb/model/type/info.rb +44 -0
- data/lib/pdfrb/model/type/ink_annotation.rb +29 -0
- data/lib/pdfrb/model/type/interactive_form.rb +36 -0
- data/lib/pdfrb/model/type/interior_color.rb +12 -0
- data/lib/pdfrb/model/type/jbig2_globals.rb +15 -0
- data/lib/pdfrb/model/type/lab.rb +27 -0
- data/lib/pdfrb/model/type/line_annotation.rb +44 -0
- data/lib/pdfrb/model/type/line_ending_styling.rb +39 -0
- data/lib/pdfrb/model/type/link_annotation.rb +41 -0
- data/lib/pdfrb/model/type/link_appearance.rb +9 -0
- data/lib/pdfrb/model/type/mark_information.rb +23 -0
- data/lib/pdfrb/model/type/marked_content_reference.rb +24 -0
- data/lib/pdfrb/model/type/markup_annotation.rb +36 -0
- data/lib/pdfrb/model/type/mdp_dict.rb +28 -0
- data/lib/pdfrb/model/type/measure.rb +39 -0
- data/lib/pdfrb/model/type/media_clip.rb +28 -0
- data/lib/pdfrb/model/type/media_offset.rb +106 -0
- data/lib/pdfrb/model/type/metadata.rb +27 -3
- data/lib/pdfrb/model/type/misc_helpers.rb +75 -0
- data/lib/pdfrb/model/type/movie.rb +28 -0
- data/lib/pdfrb/model/type/names.rb +51 -0
- data/lib/pdfrb/model/type/namespace.rb +27 -0
- data/lib/pdfrb/model/type/object_reference.rb +31 -0
- data/lib/pdfrb/model/type/object_stream.rb +38 -0
- data/lib/pdfrb/model/type/opt_content_ext.rb +94 -0
- data/lib/pdfrb/model/type/opt_content_page_element.rb +18 -0
- data/lib/pdfrb/model/type/optional_content_config.rb +56 -0
- data/lib/pdfrb/model/type/optional_content_group.rb +35 -10
- data/lib/pdfrb/model/type/optional_content_membership.rb +36 -2
- data/lib/pdfrb/model/type/optional_content_properties.rb +16 -1
- data/lib/pdfrb/model/type/outline.rb +40 -6
- data/lib/pdfrb/model/type/outline_item.rb +45 -0
- data/lib/pdfrb/model/type/output_intent.rb +30 -0
- data/lib/pdfrb/model/type/page.rb +127 -0
- data/lib/pdfrb/model/type/page_label.rb +68 -0
- data/lib/pdfrb/model/type/page_tree_node.rb +51 -16
- data/lib/pdfrb/model/type/page_tree_node_root.rb +15 -0
- data/lib/pdfrb/model/type/pattern.rb +16 -0
- data/lib/pdfrb/model/type/pattern_shading.rb +25 -0
- data/lib/pdfrb/model/type/pattern_tiling.rb +25 -0
- data/lib/pdfrb/model/type/polygon_annotation.rb +29 -0
- data/lib/pdfrb/model/type/polygon_polyline.rb +14 -0
- data/lib/pdfrb/model/type/polyline_annotation.rb +29 -0
- data/lib/pdfrb/model/type/popup_annotation.rb +20 -0
- data/lib/pdfrb/model/type/printer_mark_annotation.rb +13 -0
- data/lib/pdfrb/model/type/redact_annotation.rb +28 -0
- data/lib/pdfrb/model/type/rendition.rb +31 -0
- data/lib/pdfrb/model/type/resources.rb +59 -14
- data/lib/pdfrb/model/type/rich_media_activation.rb +24 -0
- data/lib/pdfrb/model/type/rich_media_animation.rb +25 -0
- data/lib/pdfrb/model/type/rich_media_annotation.rb +18 -0
- data/lib/pdfrb/model/type/rich_media_command.rb +19 -0
- data/lib/pdfrb/model/type/rich_media_configuration.rb +32 -0
- data/lib/pdfrb/model/type/rich_media_content.rb +28 -0
- data/lib/pdfrb/model/type/rich_media_cue_point.rb +18 -0
- data/lib/pdfrb/model/type/rich_media_deactivation.rb +17 -0
- data/lib/pdfrb/model/type/rich_media_instance.rb +33 -0
- data/lib/pdfrb/model/type/rich_media_presentation.rb +29 -0
- data/lib/pdfrb/model/type/rich_media_settings.rb +33 -0
- data/lib/pdfrb/model/type/rich_media_window.rb +20 -0
- data/lib/pdfrb/model/type/screen_annotation.rb +19 -0
- data/lib/pdfrb/model/type/separation.rb +25 -0
- data/lib/pdfrb/model/type/sig_field_lock.rb +25 -0
- data/lib/pdfrb/model/type/sig_field_seed_value.rb +25 -0
- data/lib/pdfrb/model/type/signature.rb +65 -0
- data/lib/pdfrb/model/type/signature_build.rb +86 -0
- data/lib/pdfrb/model/type/signature_field.rb +17 -0
- data/lib/pdfrb/model/type/software_identifier.rb +19 -0
- data/lib/pdfrb/model/type/sound.rb +38 -0
- data/lib/pdfrb/model/type/sound_annotation.rb +21 -0
- data/lib/pdfrb/model/type/square_annotation.rb +24 -0
- data/lib/pdfrb/model/type/square_circle.rb +13 -0
- data/lib/pdfrb/model/type/squiggly_annotation.rb +11 -0
- data/lib/pdfrb/model/type/stamp_annotation.rb +19 -0
- data/lib/pdfrb/model/type/strikeout_annotation.rb +11 -0
- data/lib/pdfrb/model/type/struct_elem.rb +75 -0
- data/lib/pdfrb/model/type/struct_tree_root.rb +34 -0
- data/lib/pdfrb/model/type/structure_attributes.rb +44 -0
- data/lib/pdfrb/model/type/structure_element_kid.rb +33 -0
- data/lib/pdfrb/model/type/text_annotation.rb +25 -0
- data/lib/pdfrb/model/type/text_appearance.rb +9 -0
- data/lib/pdfrb/model/type/text_field.rb +21 -0
- data/lib/pdfrb/model/type/text_markup_annotation.rb +30 -0
- data/lib/pdfrb/model/type/three_d_activation.rb +32 -0
- data/lib/pdfrb/model/type/three_d_animation_style.rb +24 -0
- data/lib/pdfrb/model/type/three_d_background.rb +28 -0
- data/lib/pdfrb/model/type/three_d_cross_section.rb +25 -0
- data/lib/pdfrb/model/type/three_d_lighting_scheme.rb +26 -0
- data/lib/pdfrb/model/type/three_d_measure.rb +20 -0
- data/lib/pdfrb/model/type/three_d_measure_3dc.rb +23 -0
- data/lib/pdfrb/model/type/three_d_measure_ad3.rb +14 -0
- data/lib/pdfrb/model/type/three_d_measure_ld3.rb +14 -0
- data/lib/pdfrb/model/type/three_d_measure_pd3.rb +20 -0
- data/lib/pdfrb/model/type/three_d_measure_rd3.rb +14 -0
- data/lib/pdfrb/model/type/three_d_node.rb +37 -0
- data/lib/pdfrb/model/type/three_d_reference.rb +21 -0
- data/lib/pdfrb/model/type/three_d_render_mode.rb +34 -0
- data/lib/pdfrb/model/type/three_d_stream.rb +48 -0
- data/lib/pdfrb/model/type/three_d_units.rb +18 -0
- data/lib/pdfrb/model/type/three_d_view.rb +40 -0
- data/lib/pdfrb/model/type/to_unicode_cmap_stream.rb +23 -0
- data/lib/pdfrb/model/type/transition.rb +68 -0
- data/lib/pdfrb/model/type/underline_annotation.rb +11 -0
- data/lib/pdfrb/model/type/ur_transform_parameters.rb +33 -0
- data/lib/pdfrb/model/type/uri_dict.rb +18 -0
- data/lib/pdfrb/model/type/url_alias.rb +19 -0
- data/lib/pdfrb/model/type/variable_text_field.rb +47 -0
- data/lib/pdfrb/model/type/viewer_preferences.rb +42 -0
- data/lib/pdfrb/model/type/watermark_annotation.rb +13 -0
- data/lib/pdfrb/model/type/widget_annotation.rb +48 -0
- data/lib/pdfrb/model/type/widget_appearance.rb +9 -0
- data/lib/pdfrb/model/type/xobject_form.rb +41 -0
- data/lib/pdfrb/model/type/xobject_image.rb +56 -0
- data/lib/pdfrb/model/type/xref_stream.rb +37 -0
- data/lib/pdfrb/model/type.rb +286 -6
- data/lib/pdfrb/serializer.rb +2 -2
- data/lib/pdfrb/source/tokenizer.rb +0 -2
- data/lib/pdfrb/task/benchmark.rb +83 -0
- data/lib/pdfrb/task/extract_text.rb +1 -1
- data/lib/pdfrb/task/generate_corpus.rb +130 -0
- data/lib/pdfrb/task/memory_profile.rb +84 -0
- data/lib/pdfrb/task/optimize.rb +97 -7
- data/lib/pdfrb/task.rb +3 -3
- data/lib/pdfrb/test_utils.rb +112 -0
- data/lib/pdfrb/validator.rb +82 -0
- data/lib/pdfrb/version.rb +1 -1
- data/lib/pdfrb/writer.rb +117 -27
- data/lib/pdfrb/xmp/packet.rb +122 -0
- data/lib/pdfrb/xmp/schemas.rb +96 -0
- data/lib/pdfrb/xmp.rb +44 -0
- data/lib/pdfrb/xref_section.rb +2 -2
- data/lib/pdfrb.rb +25 -53
- data/pdfrb.gemspec +45 -0
- data/script/apply_fixes.sh +843 -0
- data/script/make_jpeg_fixture.rb +53 -0
- data/script/make_png_fixture.rb +25 -0
- metadata +312 -2
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pdfrb
|
|
4
|
+
module Annotation
|
|
5
|
+
# Base annotation builder. Subclasses override +subtype+ and
|
|
6
|
+
# +default_fields+ to provide type-specific defaults. Each subclass
|
|
7
|
+
# calls +register_as+ at load time.
|
|
8
|
+
class Base
|
|
9
|
+
class << self
|
|
10
|
+
# @return [Symbol] the /Subtype value (e.g. :Link).
|
|
11
|
+
def subtype
|
|
12
|
+
raise NotImplementedError, "#{self} must define subtype"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Extra fields to merge into the annotation dict.
|
|
16
|
+
# @return [Hash]
|
|
17
|
+
def default_fields
|
|
18
|
+
{}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Create the annotation and attach it to the page's /Annots.
|
|
22
|
+
def create(document:, page:, rect:, **opts)
|
|
23
|
+
dict = base_dict(page: page, rect: rect, **opts).merge!(default_fields).merge!(type_overrides(opts))
|
|
24
|
+
annot = document.add(dict, type: Pdfrb::Model::Type::Annotation)
|
|
25
|
+
attach_to_page(page, annot)
|
|
26
|
+
annot
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Register this class in the Annotation registry.
|
|
30
|
+
def register_as(symbol = subtype)
|
|
31
|
+
Annotation.register(symbol, self)
|
|
32
|
+
self
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def base_dict(page:, rect:, contents: nil, flags: 0, **)
|
|
38
|
+
{
|
|
39
|
+
Type: :Annot,
|
|
40
|
+
Subtype: subtype,
|
|
41
|
+
Rect: rect,
|
|
42
|
+
P: Pdfrb::Model::Reference.new(page.oid, page.gen),
|
|
43
|
+
Contents: contents,
|
|
44
|
+
F: flags,
|
|
45
|
+
}.compact
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def type_overrides(opts)
|
|
49
|
+
overrides = {}
|
|
50
|
+
overrides[:C] = opts[:color] if opts.key?(:color)
|
|
51
|
+
overrides[:Border] = opts[:border] if opts.key?(:border)
|
|
52
|
+
overrides[:A] = opts[:action] if opts.key?(:action)
|
|
53
|
+
overrides[:Dest] = opts[:dest] if opts.key?(:dest)
|
|
54
|
+
overrides[:H] = opts[:highlight] if opts.key?(:highlight)
|
|
55
|
+
overrides[:BS] = opts[:border_style] if opts.key?(:border_style)
|
|
56
|
+
overrides[:QuadPoints] = opts[:quad_points] if opts.key?(:quad_points)
|
|
57
|
+
overrides[:T] = opts[:title] if opts.key?(:title)
|
|
58
|
+
overrides[:RC] = opts[:rich_contents] if opts.key?(:rich_contents)
|
|
59
|
+
overrides[:CreationDate] = opts[:created_at] if opts.key?(:created_at)
|
|
60
|
+
overrides[:M] = opts[:modified_at] if opts.key?(:modified_at)
|
|
61
|
+
overrides[:NM] = opts[:name] if opts.key?(:name)
|
|
62
|
+
overrides.compact
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def attach_to_page(page, annot)
|
|
66
|
+
annots = page.value[:Annots]
|
|
67
|
+
ref = Pdfrb::Model::Reference.new(annot.oid, annot.gen)
|
|
68
|
+
if annots.nil?
|
|
69
|
+
page.value[:Annots] = [ref]
|
|
70
|
+
elsif annots.is_a?(::Array)
|
|
71
|
+
annots << ref
|
|
72
|
+
else
|
|
73
|
+
page.value[:Annots] = [annots, ref]
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pdfrb
|
|
4
|
+
module Annotation
|
|
5
|
+
# Concrete annotation types (ISO 32000-2 §12.5.6). Each class
|
|
6
|
+
# defines its /Subtype and type-specific defaults, then registers
|
|
7
|
+
# itself via +register_as+.
|
|
8
|
+
#
|
|
9
|
+
# OCP: new annotation type = new class + register_as. No edits
|
|
10
|
+
# to existing code.
|
|
11
|
+
|
|
12
|
+
# Text annotation (sticky note). §12.5.6.4
|
|
13
|
+
class Text < Base
|
|
14
|
+
class << self
|
|
15
|
+
def subtype; :Text; end
|
|
16
|
+
|
|
17
|
+
def default_fields
|
|
18
|
+
{ Name: :Comment }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
register_as
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Link annotation (hyperlink). §12.5.6.5
|
|
25
|
+
class Link < Base
|
|
26
|
+
class << self
|
|
27
|
+
def subtype; :Link; end
|
|
28
|
+
|
|
29
|
+
def default_fields
|
|
30
|
+
{ H: :I } # Invert highlight by default
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
register_as
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# FreeText annotation (free-form text box). §12.5.6.6
|
|
37
|
+
class FreeText < Base
|
|
38
|
+
class << self
|
|
39
|
+
def subtype; :FreeText; end
|
|
40
|
+
|
|
41
|
+
def default_fields
|
|
42
|
+
{ DA: "/Helv 0 Tf 0 g" }
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
register_as
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Stamp annotation (rubber stamp). §12.5.6.8
|
|
49
|
+
class Stamp < Base
|
|
50
|
+
class << self
|
|
51
|
+
def subtype; :Stamp; end
|
|
52
|
+
|
|
53
|
+
def default_fields
|
|
54
|
+
{ Name: :Draft }
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
register_as
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Popup annotation. §12.5.6.13. Usually paired with a markup annot
|
|
61
|
+
# via the markup's /Popup key.
|
|
62
|
+
class Popup < Base
|
|
63
|
+
class << self
|
|
64
|
+
def subtype; :Popup; end
|
|
65
|
+
|
|
66
|
+
def default_fields
|
|
67
|
+
{ Open: false }
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
register_as
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# FileAttachment annotation (embedded file). §12.5.6.15
|
|
74
|
+
# Inspired by mn2pdf's FileAttachmentAnnotation.
|
|
75
|
+
class FileAttachment < Base
|
|
76
|
+
class << self
|
|
77
|
+
def subtype; :FileAttachment; end
|
|
78
|
+
|
|
79
|
+
def default_fields
|
|
80
|
+
{ Name: :PushPin }
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
register_as
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Highlight (text markup). §12.5.6.10
|
|
87
|
+
class Highlight < Base
|
|
88
|
+
class << self
|
|
89
|
+
def subtype; :Highlight; end
|
|
90
|
+
end
|
|
91
|
+
register_as
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Underline (text markup). §12.5.6.10
|
|
95
|
+
class Underline < Base
|
|
96
|
+
class << self
|
|
97
|
+
def subtype; :Underline; end
|
|
98
|
+
end
|
|
99
|
+
register_as
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Squiggly (text markup). §12.5.6.10
|
|
103
|
+
class Squiggly < Base
|
|
104
|
+
class << self
|
|
105
|
+
def subtype; :Squiggly; end
|
|
106
|
+
end
|
|
107
|
+
register_as
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# StrikeOut (text markup). §12.5.6.10
|
|
111
|
+
class StrikeOut < Base
|
|
112
|
+
class << self
|
|
113
|
+
def subtype; :StrikeOut; end
|
|
114
|
+
end
|
|
115
|
+
register_as
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Square (shape markup). §12.5.6.8
|
|
119
|
+
class Square < Base
|
|
120
|
+
class << self
|
|
121
|
+
def subtype; :Square; end
|
|
122
|
+
end
|
|
123
|
+
register_as
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Circle (shape markup). §12.5.6.8
|
|
127
|
+
class Circle < Base
|
|
128
|
+
class << self
|
|
129
|
+
def subtype; :Circle; end
|
|
130
|
+
end
|
|
131
|
+
register_as
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Line annotation. §12.5.6.7
|
|
135
|
+
class Line < Base
|
|
136
|
+
class << self
|
|
137
|
+
def subtype; :Line; end
|
|
138
|
+
end
|
|
139
|
+
register_as
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Polygon annotation. §12.5.6.9
|
|
143
|
+
class Polygon < Base
|
|
144
|
+
class << self
|
|
145
|
+
def subtype; :Polygon; end
|
|
146
|
+
end
|
|
147
|
+
register_as
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Polyline annotation. §12.5.6.9
|
|
151
|
+
class Polyline < Base
|
|
152
|
+
class << self
|
|
153
|
+
def subtype; :Polyline; end
|
|
154
|
+
end
|
|
155
|
+
register_as
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Ink annotation (freehand). §12.5.6.13
|
|
159
|
+
class Ink < Base
|
|
160
|
+
class << self
|
|
161
|
+
def subtype; :Ink; end
|
|
162
|
+
end
|
|
163
|
+
register_as
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Widget annotation (form field). §12.5.6.19
|
|
167
|
+
class Widget < Base
|
|
168
|
+
class << self
|
|
169
|
+
def subtype; :Widget; end
|
|
170
|
+
end
|
|
171
|
+
register_as
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Caret annotation. §12.5.6.11
|
|
175
|
+
class Caret < Base
|
|
176
|
+
class << self
|
|
177
|
+
def subtype; :Caret; end
|
|
178
|
+
end
|
|
179
|
+
register_as
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Redact annotation. §12.5.6.16
|
|
183
|
+
class Redact < Base
|
|
184
|
+
class << self
|
|
185
|
+
def subtype; :Redact; end
|
|
186
|
+
end
|
|
187
|
+
register_as
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Watermark annotation. §12.5.6.23 (PDF 2.0)
|
|
191
|
+
class Watermark < Base
|
|
192
|
+
class << self
|
|
193
|
+
def subtype; :Watermark; end
|
|
194
|
+
end
|
|
195
|
+
register_as
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# PrinterMark annotation. §12.5.6.17
|
|
199
|
+
class PrinterMark < Base
|
|
200
|
+
class << self
|
|
201
|
+
def subtype; :PrinterMark; end
|
|
202
|
+
end
|
|
203
|
+
register_as
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Screen annotation. §12.5.6.18
|
|
207
|
+
class Screen < Base
|
|
208
|
+
class << self
|
|
209
|
+
def subtype; :Screen; end
|
|
210
|
+
end
|
|
211
|
+
register_as
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Sound annotation. §12.5.6.18
|
|
215
|
+
class Sound < Base
|
|
216
|
+
class << self
|
|
217
|
+
def subtype; :Sound; end
|
|
218
|
+
end
|
|
219
|
+
register_as
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pdfrb
|
|
4
|
+
# Annotation types (ISO 32000-2 §12.5). Each subtype is a thin builder
|
|
5
|
+
# that produces a correctly-shaped annotation dictionary and registers
|
|
6
|
+
# itself in the +Annotation::REGISTRY+ for open/closed extensibility.
|
|
7
|
+
module Annotation
|
|
8
|
+
autoload :Base, "pdfrb/annotation/base"
|
|
9
|
+
autoload :Types, "pdfrb/annotation/types"
|
|
10
|
+
# Each annotation builder class lives in types.rb. Autoload from
|
|
11
|
+
# that file so direct class references work.
|
|
12
|
+
autoload :Text, "pdfrb/annotation/types"
|
|
13
|
+
autoload :Link, "pdfrb/annotation/types"
|
|
14
|
+
autoload :FreeText, "pdfrb/annotation/types"
|
|
15
|
+
autoload :Stamp, "pdfrb/annotation/types"
|
|
16
|
+
autoload :Popup, "pdfrb/annotation/types"
|
|
17
|
+
autoload :FileAttachment, "pdfrb/annotation/types"
|
|
18
|
+
autoload :Highlight, "pdfrb/annotation/types"
|
|
19
|
+
autoload :Underline, "pdfrb/annotation/types"
|
|
20
|
+
autoload :Squiggly, "pdfrb/annotation/types"
|
|
21
|
+
autoload :StrikeOut, "pdfrb/annotation/types"
|
|
22
|
+
autoload :Square, "pdfrb/annotation/types"
|
|
23
|
+
autoload :Circle, "pdfrb/annotation/types"
|
|
24
|
+
autoload :Line, "pdfrb/annotation/types"
|
|
25
|
+
autoload :Polygon, "pdfrb/annotation/types"
|
|
26
|
+
autoload :Polyline, "pdfrb/annotation/types"
|
|
27
|
+
autoload :Ink, "pdfrb/annotation/types"
|
|
28
|
+
autoload :Widget, "pdfrb/annotation/types"
|
|
29
|
+
autoload :Caret, "pdfrb/annotation/types"
|
|
30
|
+
autoload :Redact, "pdfrb/annotation/types"
|
|
31
|
+
autoload :Watermark, "pdfrb/annotation/types"
|
|
32
|
+
autoload :PrinterMark, "pdfrb/annotation/types"
|
|
33
|
+
autoload :Screen, "pdfrb/annotation/types"
|
|
34
|
+
autoload :Sound, "pdfrb/annotation/types"
|
|
35
|
+
|
|
36
|
+
class << self
|
|
37
|
+
def create(subtype, document:, page:, **opts)
|
|
38
|
+
ensure_loaded
|
|
39
|
+
klass = registry[subtype]
|
|
40
|
+
return build_fallback(subtype, document, page, opts) unless klass
|
|
41
|
+
|
|
42
|
+
klass.create(document: document, page: page, **opts)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def registry
|
|
46
|
+
@registry ||= {}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def register(subtype, klass)
|
|
50
|
+
registry[subtype] = klass
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def [](subtype)
|
|
54
|
+
ensure_loaded
|
|
55
|
+
registry[subtype]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def subtypes
|
|
59
|
+
ensure_loaded
|
|
60
|
+
registry.keys
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def ensure_loaded
|
|
66
|
+
return if @loaded
|
|
67
|
+
|
|
68
|
+
# Trigger the types.rb load which registers all subtypes.
|
|
69
|
+
Pdfrb::Annotation::Text
|
|
70
|
+
@loaded = true
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def build_fallback(subtype, document, page, opts)
|
|
74
|
+
Base.create(subtype, document: document, page: page, **opts)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "stringio"
|
|
4
|
+
|
|
5
|
+
module Pdfrb
|
|
6
|
+
module Appearance
|
|
7
|
+
# Generates /AP /N appearance streams for form fields and annotations.
|
|
8
|
+
# Each method creates a Form XObject with the field's visual
|
|
9
|
+
# representation and sets it as the /AP /N entry on the field.
|
|
10
|
+
#
|
|
11
|
+
# For PDF/A-4, /NeedAppearances must be false (or absent), so every
|
|
12
|
+
# field needs a pre-computed appearance stream.
|
|
13
|
+
class Generator
|
|
14
|
+
DEFAULT_BORDER_WIDTH = 1.0
|
|
15
|
+
DEFAULT_FONT_SIZE = 12
|
|
16
|
+
DEFAULT_PADDING = 3
|
|
17
|
+
|
|
18
|
+
attr_reader :document
|
|
19
|
+
|
|
20
|
+
def initialize(document)
|
|
21
|
+
@document = document
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Generate appearance for a text field.
|
|
25
|
+
# @param field [Pdfrb::Model::Type::Annotation] the Widget/field.
|
|
26
|
+
# @param value [String] the text value to display.
|
|
27
|
+
# @param font_name [Symbol] resource name of the font.
|
|
28
|
+
# @param font_size [Integer] point size.
|
|
29
|
+
def text_field(field, value:, font_name: :Helv, font_size: DEFAULT_FONT_SIZE)
|
|
30
|
+
rect = field.value[:Rect]
|
|
31
|
+
return unless rect
|
|
32
|
+
|
|
33
|
+
form = build_form_xobject(rect) do |canvas|
|
|
34
|
+
draw_border(canvas, rect)
|
|
35
|
+
if value && !value.to_s.empty?
|
|
36
|
+
canvas.text(value.to_s,
|
|
37
|
+
at: [DEFAULT_PADDING, DEFAULT_PADDING],
|
|
38
|
+
font: font_name, size: font_size)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
set_appearance(field, form)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Generate appearance for a checkbox.
|
|
46
|
+
# @param field [Pdfrb::Model::Type::Annotation] the Widget/field.
|
|
47
|
+
# @param checked [Boolean] whether the box is checked.
|
|
48
|
+
def checkbox(field, checked:)
|
|
49
|
+
rect = field.value[:Rect]
|
|
50
|
+
return unless rect
|
|
51
|
+
|
|
52
|
+
form = build_form_xobject(rect) do |canvas|
|
|
53
|
+
draw_border(canvas, rect)
|
|
54
|
+
if checked
|
|
55
|
+
draw_check(canvas, rect)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
state_name = checked ? :Yes : :Off
|
|
60
|
+
set_appearance(field, form, state_name)
|
|
61
|
+
field.value[:AS] = state_name
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Generate appearance for a combo box (dropdown).
|
|
65
|
+
# @param field [Pdfrb::Model::Type::Annotation] the Widget/field.
|
|
66
|
+
# @param value [String] the selected value.
|
|
67
|
+
# @param font_name [Symbol] resource name of the font.
|
|
68
|
+
# @param font_size [Integer] point size.
|
|
69
|
+
def combo(field, value:, font_name: :Helv, font_size: DEFAULT_FONT_SIZE)
|
|
70
|
+
text_field(field, value: value, font_name: font_name, font_size: font_size)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Generate appearance for a push button.
|
|
74
|
+
# @param field [Pdfrb::Model::Type::Annotation] the Widget/field.
|
|
75
|
+
# @param label [String] the button label.
|
|
76
|
+
# @param font_name [Symbol] resource name of the font.
|
|
77
|
+
def button(field, label:, font_name: :Helv)
|
|
78
|
+
rect = field.value[:Rect]
|
|
79
|
+
return unless rect
|
|
80
|
+
|
|
81
|
+
form = build_form_xobject(rect) do |canvas|
|
|
82
|
+
draw_border(canvas, rect)
|
|
83
|
+
if label
|
|
84
|
+
w = rect[2] - rect[0]
|
|
85
|
+
h = rect[3] - rect[1]
|
|
86
|
+
canvas.text(label,
|
|
87
|
+
at: [w / 3, h / 3],
|
|
88
|
+
font: font_name, size: DEFAULT_FONT_SIZE)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
set_appearance(field, form)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Generate appearance for a radio button.
|
|
96
|
+
# @param field [Pdfrb::Model::Type::Annotation] the Widget/field.
|
|
97
|
+
# @param selected [String] the selected state name (e.g. :Yes).
|
|
98
|
+
# @param options [Array<String>] all possible state names.
|
|
99
|
+
def radio_button(field, selected:, options: [:Yes])
|
|
100
|
+
rect = field.value[:Rect]
|
|
101
|
+
return unless rect
|
|
102
|
+
|
|
103
|
+
options.each do |state|
|
|
104
|
+
form = build_form_xobject(rect) do |canvas|
|
|
105
|
+
draw_border(canvas, rect)
|
|
106
|
+
draw_radio_circle(canvas, rect, selected: state == selected)
|
|
107
|
+
end
|
|
108
|
+
set_appearance(field, form, state_name: state.to_sym)
|
|
109
|
+
end
|
|
110
|
+
field.value[:AS] = selected.to_sym
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Generate appearance for a list box field.
|
|
114
|
+
# @param field [Pdfrb::Model::Type::Annotation] the Widget/field.
|
|
115
|
+
# @param items [Array<String>] the list items to show.
|
|
116
|
+
# @param selected [Integer, nil] index of the selected item.
|
|
117
|
+
# @param font_name [Symbol] resource name of the font.
|
|
118
|
+
# @param font_size [Integer] point size.
|
|
119
|
+
def list_box(field, items:, selected: nil, font_name: :Helv,
|
|
120
|
+
font_size: DEFAULT_FONT_SIZE)
|
|
121
|
+
rect = field.value[:Rect]
|
|
122
|
+
return unless rect
|
|
123
|
+
|
|
124
|
+
form = build_form_xobject(rect) do |canvas|
|
|
125
|
+
draw_border(canvas, rect)
|
|
126
|
+
items.each_with_index do |item, i|
|
|
127
|
+
y_pos = (rect[3] - rect[1]) - DEFAULT_PADDING - ((i + 1) * font_size)
|
|
128
|
+
break if y_pos.negative?
|
|
129
|
+
|
|
130
|
+
if i == selected
|
|
131
|
+
w = rect[2] - rect[0]
|
|
132
|
+
canvas.fill_color([0.8, 0.8, 1.0])
|
|
133
|
+
canvas.rectangle(0, y_pos - 2, w, font_size + 4)
|
|
134
|
+
canvas.fill
|
|
135
|
+
canvas.fill_color([0, 0, 0])
|
|
136
|
+
end
|
|
137
|
+
canvas.text(item.to_s, at: [DEFAULT_PADDING, y_pos],
|
|
138
|
+
font: font_name, size: font_size)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
set_appearance(field, form)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
private
|
|
145
|
+
|
|
146
|
+
def build_form_xobject(rect)
|
|
147
|
+
x0, y0, x1, y1 = rect
|
|
148
|
+
form = document.create_form_xobject(
|
|
149
|
+
name: "AP",
|
|
150
|
+
bbox: [0, 0, x1 - x0, y1 - y0]
|
|
151
|
+
)
|
|
152
|
+
canvas = form.canvas
|
|
153
|
+
yield canvas
|
|
154
|
+
form.finalize!
|
|
155
|
+
form
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def draw_border(canvas, rect)
|
|
159
|
+
w = rect[2] - rect[0]
|
|
160
|
+
h = rect[3] - rect[1]
|
|
161
|
+
canvas.line_width = 0.5
|
|
162
|
+
canvas.rectangle(0, 0, w, h)
|
|
163
|
+
canvas.stroke
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def draw_radio_circle(canvas, rect, selected:)
|
|
167
|
+
w = rect[2] - rect[0]
|
|
168
|
+
h = rect[3] - rect[1]
|
|
169
|
+
r = ([w, h].min / 2) - 1
|
|
170
|
+
cx = w / 2
|
|
171
|
+
cy = h / 2
|
|
172
|
+
canvas.line_width = 1.0
|
|
173
|
+
|
|
174
|
+
# Approximate a circle with a rectangle for now (Canvas lacks arc).
|
|
175
|
+
canvas.rectangle(cx - r, cy - r, r * 2, r * 2)
|
|
176
|
+
canvas.stroke
|
|
177
|
+
|
|
178
|
+
if selected
|
|
179
|
+
canvas.line_width = 2.0
|
|
180
|
+
inner_r = r * 0.4
|
|
181
|
+
canvas.rectangle(cx - inner_r, cy - inner_r, inner_r * 2, inner_r * 2)
|
|
182
|
+
canvas.fill
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def draw_check(canvas, rect)
|
|
187
|
+
w = rect[2] - rect[0]
|
|
188
|
+
h = rect[3] - rect[1]
|
|
189
|
+
m = [w * 0.2, h * 0.2].min
|
|
190
|
+
canvas.line_width = 1.5
|
|
191
|
+
canvas.line(m, m, w - m, h - m)
|
|
192
|
+
canvas.line(m, h - m, w - m, m)
|
|
193
|
+
canvas.stroke
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def set_appearance(field, form, state_name = :Normal)
|
|
197
|
+
form_stream = form.stream
|
|
198
|
+
ref = Pdfrb::Model::Reference.new(form_stream.oid, form_stream.gen)
|
|
199
|
+
|
|
200
|
+
ap = field.value[:AP]
|
|
201
|
+
if ap.nil?
|
|
202
|
+
ap = {}
|
|
203
|
+
field.value[:AP] = ap
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
if state_name == :Normal
|
|
207
|
+
ap[:N] = ref
|
|
208
|
+
else
|
|
209
|
+
n_dict = ap[:N].is_a?(::Hash) ? ap[:N] : {}
|
|
210
|
+
n_dict[state_name] = ref
|
|
211
|
+
ap[:N] = n_dict
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pdfrb
|
|
4
|
+
# Appearance stream generation (ISO 32000-2 §12.5.5). Generates
|
|
5
|
+
# /AP /N (normal appearance) streams for form fields and annotations
|
|
6
|
+
# using the Canvas API. Required for PDF/A-4 compliance (which
|
|
7
|
+
# prohibits /NeedAppearances).
|
|
8
|
+
module Appearance
|
|
9
|
+
autoload :Generator, "pdfrb/appearance/generator"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -9,8 +9,18 @@ module Pdfrb
|
|
|
9
9
|
module Functions
|
|
10
10
|
@registry = {}
|
|
11
11
|
|
|
12
|
+
autoload :VersionPredicates, "pdfrb/arlington/predicate/functions/version"
|
|
13
|
+
autoload :PresencePredicates, "pdfrb/arlington/predicate/functions/presence"
|
|
14
|
+
autoload :LogicalPredicates, "pdfrb/arlington/predicate/functions/logical"
|
|
15
|
+
autoload :ArithmeticPredicates, "pdfrb/arlington/predicate/functions/arithmetic"
|
|
16
|
+
autoload :ReferencePredicates, "pdfrb/arlington/predicate/functions/reference"
|
|
17
|
+
autoload :FilePredicates, "pdfrb/arlington/predicate/functions/file"
|
|
18
|
+
|
|
12
19
|
class << self
|
|
13
|
-
|
|
20
|
+
def registry
|
|
21
|
+
eager_load! unless @eager_loaded
|
|
22
|
+
@registry
|
|
23
|
+
end
|
|
14
24
|
|
|
15
25
|
def register(name, &block)
|
|
16
26
|
@registry[name.to_s] = block
|
|
@@ -19,16 +29,22 @@ module Pdfrb
|
|
|
19
29
|
def clear!
|
|
20
30
|
@registry.clear
|
|
21
31
|
end
|
|
32
|
+
|
|
33
|
+
# Force-load all function groups so register calls fire.
|
|
34
|
+
# Idempotent.
|
|
35
|
+
def eager_load!
|
|
36
|
+
return if @eager_loaded
|
|
37
|
+
|
|
38
|
+
constants.each do |c|
|
|
39
|
+
const_get(c)
|
|
40
|
+
rescue NameError, LoadError
|
|
41
|
+
# Skip autoload targets that don't define a class
|
|
42
|
+
# or whose file doesn't exist yet.
|
|
43
|
+
end
|
|
44
|
+
@eager_loaded = true
|
|
45
|
+
end
|
|
22
46
|
end
|
|
23
47
|
end
|
|
24
48
|
end
|
|
25
49
|
end
|
|
26
50
|
end
|
|
27
|
-
|
|
28
|
-
# Load built-in function groups. Each calls Functions.register on load.
|
|
29
|
-
require "pdfrb/arlington/predicate/functions/version"
|
|
30
|
-
require "pdfrb/arlington/predicate/functions/presence"
|
|
31
|
-
require "pdfrb/arlington/predicate/functions/logical"
|
|
32
|
-
require "pdfrb/arlington/predicate/functions/arithmetic"
|
|
33
|
-
require "pdfrb/arlington/predicate/functions/reference"
|
|
34
|
-
require "pdfrb/arlington/predicate/functions/file"
|
|
@@ -12,11 +12,7 @@ module Pdfrb
|
|
|
12
12
|
autoload :AST, "pdfrb/arlington/predicate/ast"
|
|
13
13
|
autoload :Evaluator, "pdfrb/arlington/predicate/evaluator"
|
|
14
14
|
autoload :Context, "pdfrb/arlington/predicate/context"
|
|
15
|
+
autoload :Functions, "pdfrb/arlington/predicate/functions"
|
|
15
16
|
end
|
|
16
17
|
end
|
|
17
18
|
end
|
|
18
|
-
|
|
19
|
-
# Eager-load the function registry so predicates are registered as
|
|
20
|
-
# soon as the Predicate namespace is touched. (Functions.register is
|
|
21
|
-
# called at the bottom of each functions/*.rb.)
|
|
22
|
-
require "pdfrb/arlington/predicate/functions"
|