hexapdf 0.1.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 +7 -0
- data/CONTRIBUTERS +3 -0
- data/LICENSE +26 -0
- data/README.md +88 -0
- data/Rakefile +121 -0
- data/VERSION +1 -0
- data/agpl-3.0.txt +661 -0
- data/bin/hexapdf +6 -0
- data/data/hexapdf/afm/Courier-Bold.afm +342 -0
- data/data/hexapdf/afm/Courier-BoldOblique.afm +342 -0
- data/data/hexapdf/afm/Courier-Oblique.afm +342 -0
- data/data/hexapdf/afm/Courier.afm +342 -0
- data/data/hexapdf/afm/Helvetica-Bold.afm +2827 -0
- data/data/hexapdf/afm/Helvetica-BoldOblique.afm +2827 -0
- data/data/hexapdf/afm/Helvetica-Oblique.afm +3051 -0
- data/data/hexapdf/afm/Helvetica.afm +3051 -0
- data/data/hexapdf/afm/MustRead.html +1 -0
- data/data/hexapdf/afm/Symbol.afm +213 -0
- data/data/hexapdf/afm/Times-Bold.afm +2588 -0
- data/data/hexapdf/afm/Times-BoldItalic.afm +2384 -0
- data/data/hexapdf/afm/Times-Italic.afm +2667 -0
- data/data/hexapdf/afm/Times-Roman.afm +2419 -0
- data/data/hexapdf/afm/ZapfDingbats.afm +225 -0
- data/data/hexapdf/encoding/glyphlist.txt +4305 -0
- data/data/hexapdf/encoding/zapfdingbats.txt +225 -0
- data/examples/arc.rb +50 -0
- data/examples/graphics.rb +274 -0
- data/examples/hello_world.rb +16 -0
- data/examples/machupicchu.jpg +0 -0
- data/examples/merging.rb +24 -0
- data/examples/optimizing.rb +20 -0
- data/examples/show_char_bboxes.rb +55 -0
- data/examples/standard_pdf_fonts.rb +72 -0
- data/examples/truetype.rb +45 -0
- data/lib/hexapdf/cli/extract.rb +128 -0
- data/lib/hexapdf/cli/info.rb +121 -0
- data/lib/hexapdf/cli/inspect.rb +157 -0
- data/lib/hexapdf/cli/modify.rb +218 -0
- data/lib/hexapdf/cli.rb +121 -0
- data/lib/hexapdf/configuration.rb +392 -0
- data/lib/hexapdf/content/canvas.rb +1974 -0
- data/lib/hexapdf/content/color_space.rb +364 -0
- data/lib/hexapdf/content/graphic_object/arc.rb +267 -0
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +208 -0
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +173 -0
- data/lib/hexapdf/content/graphic_object.rb +81 -0
- data/lib/hexapdf/content/graphics_state.rb +579 -0
- data/lib/hexapdf/content/operator.rb +1072 -0
- data/lib/hexapdf/content/parser.rb +204 -0
- data/lib/hexapdf/content/processor.rb +451 -0
- data/lib/hexapdf/content/transformation_matrix.rb +172 -0
- data/lib/hexapdf/content.rb +47 -0
- data/lib/hexapdf/data_dir.rb +51 -0
- data/lib/hexapdf/dictionary.rb +303 -0
- data/lib/hexapdf/dictionary_fields.rb +382 -0
- data/lib/hexapdf/document.rb +589 -0
- data/lib/hexapdf/document_utils.rb +209 -0
- data/lib/hexapdf/encryption/aes.rb +206 -0
- data/lib/hexapdf/encryption/arc4.rb +93 -0
- data/lib/hexapdf/encryption/fast_aes.rb +79 -0
- data/lib/hexapdf/encryption/fast_arc4.rb +67 -0
- data/lib/hexapdf/encryption/identity.rb +63 -0
- data/lib/hexapdf/encryption/ruby_aes.rb +447 -0
- data/lib/hexapdf/encryption/ruby_arc4.rb +96 -0
- data/lib/hexapdf/encryption/security_handler.rb +494 -0
- data/lib/hexapdf/encryption/standard_security_handler.rb +616 -0
- data/lib/hexapdf/encryption.rb +94 -0
- data/lib/hexapdf/error.rb +73 -0
- data/lib/hexapdf/filter/ascii85_decode.rb +160 -0
- data/lib/hexapdf/filter/ascii_hex_decode.rb +87 -0
- data/lib/hexapdf/filter/dct_decode.rb +57 -0
- data/lib/hexapdf/filter/encryption.rb +59 -0
- data/lib/hexapdf/filter/flate_decode.rb +93 -0
- data/lib/hexapdf/filter/jpx_decode.rb +56 -0
- data/lib/hexapdf/filter/lzw_decode.rb +191 -0
- data/lib/hexapdf/filter/predictor.rb +266 -0
- data/lib/hexapdf/filter/run_length_decode.rb +108 -0
- data/lib/hexapdf/filter.rb +176 -0
- data/lib/hexapdf/font/cmap/parser.rb +146 -0
- data/lib/hexapdf/font/cmap/writer.rb +176 -0
- data/lib/hexapdf/font/cmap.rb +90 -0
- data/lib/hexapdf/font/encoding/base.rb +77 -0
- data/lib/hexapdf/font/encoding/difference_encoding.rb +64 -0
- data/lib/hexapdf/font/encoding/glyph_list.rb +150 -0
- data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +221 -0
- data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +265 -0
- data/lib/hexapdf/font/encoding/standard_encoding.rb +205 -0
- data/lib/hexapdf/font/encoding/symbol_encoding.rb +244 -0
- data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +280 -0
- data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +250 -0
- data/lib/hexapdf/font/encoding.rb +68 -0
- data/lib/hexapdf/font/true_type/font.rb +179 -0
- data/lib/hexapdf/font/true_type/table/cmap.rb +103 -0
- data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +384 -0
- data/lib/hexapdf/font/true_type/table/directory.rb +92 -0
- data/lib/hexapdf/font/true_type/table/glyf.rb +166 -0
- data/lib/hexapdf/font/true_type/table/head.rb +143 -0
- data/lib/hexapdf/font/true_type/table/hhea.rb +109 -0
- data/lib/hexapdf/font/true_type/table/hmtx.rb +79 -0
- data/lib/hexapdf/font/true_type/table/loca.rb +79 -0
- data/lib/hexapdf/font/true_type/table/maxp.rb +112 -0
- data/lib/hexapdf/font/true_type/table/name.rb +218 -0
- data/lib/hexapdf/font/true_type/table/os2.rb +200 -0
- data/lib/hexapdf/font/true_type/table/post.rb +230 -0
- data/lib/hexapdf/font/true_type/table.rb +155 -0
- data/lib/hexapdf/font/true_type.rb +48 -0
- data/lib/hexapdf/font/true_type_wrapper.rb +240 -0
- data/lib/hexapdf/font/type1/afm_parser.rb +230 -0
- data/lib/hexapdf/font/type1/character_metrics.rb +67 -0
- data/lib/hexapdf/font/type1/font.rb +123 -0
- data/lib/hexapdf/font/type1/font_metrics.rb +117 -0
- data/lib/hexapdf/font/type1/pfb_parser.rb +71 -0
- data/lib/hexapdf/font/type1.rb +52 -0
- data/lib/hexapdf/font/type1_wrapper.rb +193 -0
- data/lib/hexapdf/font_loader/from_configuration.rb +70 -0
- data/lib/hexapdf/font_loader/standard14.rb +98 -0
- data/lib/hexapdf/font_loader.rb +85 -0
- data/lib/hexapdf/font_utils.rb +89 -0
- data/lib/hexapdf/image_loader/jpeg.rb +166 -0
- data/lib/hexapdf/image_loader/pdf.rb +89 -0
- data/lib/hexapdf/image_loader/png.rb +410 -0
- data/lib/hexapdf/image_loader.rb +68 -0
- data/lib/hexapdf/importer.rb +139 -0
- data/lib/hexapdf/name_tree_node.rb +78 -0
- data/lib/hexapdf/number_tree_node.rb +67 -0
- data/lib/hexapdf/object.rb +363 -0
- data/lib/hexapdf/parser.rb +349 -0
- data/lib/hexapdf/rectangle.rb +99 -0
- data/lib/hexapdf/reference.rb +98 -0
- data/lib/hexapdf/revision.rb +206 -0
- data/lib/hexapdf/revisions.rb +194 -0
- data/lib/hexapdf/serializer.rb +326 -0
- data/lib/hexapdf/stream.rb +279 -0
- data/lib/hexapdf/task/dereference.rb +109 -0
- data/lib/hexapdf/task/optimize.rb +230 -0
- data/lib/hexapdf/task.rb +68 -0
- data/lib/hexapdf/tokenizer.rb +406 -0
- data/lib/hexapdf/type/catalog.rb +107 -0
- data/lib/hexapdf/type/embedded_file.rb +87 -0
- data/lib/hexapdf/type/file_specification.rb +232 -0
- data/lib/hexapdf/type/font.rb +81 -0
- data/lib/hexapdf/type/font_descriptor.rb +109 -0
- data/lib/hexapdf/type/font_simple.rb +190 -0
- data/lib/hexapdf/type/font_true_type.rb +47 -0
- data/lib/hexapdf/type/font_type1.rb +162 -0
- data/lib/hexapdf/type/form.rb +103 -0
- data/lib/hexapdf/type/graphics_state_parameter.rb +79 -0
- data/lib/hexapdf/type/image.rb +73 -0
- data/lib/hexapdf/type/info.rb +70 -0
- data/lib/hexapdf/type/names.rb +69 -0
- data/lib/hexapdf/type/object_stream.rb +224 -0
- data/lib/hexapdf/type/page.rb +355 -0
- data/lib/hexapdf/type/page_tree_node.rb +269 -0
- data/lib/hexapdf/type/resources.rb +212 -0
- data/lib/hexapdf/type/trailer.rb +128 -0
- data/lib/hexapdf/type/viewer_preferences.rb +73 -0
- data/lib/hexapdf/type/xref_stream.rb +204 -0
- data/lib/hexapdf/type.rb +67 -0
- data/lib/hexapdf/utils/bit_field.rb +87 -0
- data/lib/hexapdf/utils/bit_stream.rb +148 -0
- data/lib/hexapdf/utils/lru_cache.rb +65 -0
- data/lib/hexapdf/utils/math_helpers.rb +55 -0
- data/lib/hexapdf/utils/object_hash.rb +130 -0
- data/lib/hexapdf/utils/pdf_doc_encoding.rb +93 -0
- data/lib/hexapdf/utils/sorted_tree_node.rb +339 -0
- data/lib/hexapdf/version.rb +39 -0
- data/lib/hexapdf/writer.rb +199 -0
- data/lib/hexapdf/xref_section.rb +152 -0
- data/lib/hexapdf.rb +34 -0
- data/man/man1/hexapdf.1 +249 -0
- data/test/data/aes-test-vectors/CBCGFSbox-128-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCGFSbox-128-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCGFSbox-192-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCGFSbox-192-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCGFSbox-256-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCGFSbox-256-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCKeySbox-128-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCKeySbox-128-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCKeySbox-192-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCKeySbox-192-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCKeySbox-256-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCKeySbox-256-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarKey-128-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarKey-128-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarKey-192-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarKey-192-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarKey-256-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarKey-256-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarTxt-128-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarTxt-128-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarTxt-192-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarTxt-192-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarTxt-256-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarTxt-256-encrypt.data.gz +0 -0
- data/test/data/fonts/Ubuntu-Title.ttf +0 -0
- data/test/data/images/cmyk.jpg +0 -0
- data/test/data/images/fillbytes.jpg +0 -0
- data/test/data/images/gray.jpg +0 -0
- data/test/data/images/greyscale-1bit.png +0 -0
- data/test/data/images/greyscale-2bit.png +0 -0
- data/test/data/images/greyscale-4bit.png +0 -0
- data/test/data/images/greyscale-8bit.png +0 -0
- data/test/data/images/greyscale-alpha-8bit.png +0 -0
- data/test/data/images/greyscale-trns-8bit.png +0 -0
- data/test/data/images/greyscale-with-gamma1.0.png +0 -0
- data/test/data/images/greyscale-with-gamma1.5.png +0 -0
- data/test/data/images/indexed-1bit.png +0 -0
- data/test/data/images/indexed-2bit.png +0 -0
- data/test/data/images/indexed-4bit.png +0 -0
- data/test/data/images/indexed-8bit.png +0 -0
- data/test/data/images/indexed-alpha-4bit.png +0 -0
- data/test/data/images/indexed-alpha-8bit.png +0 -0
- data/test/data/images/rgb.jpg +0 -0
- data/test/data/images/truecolour-8bit.png +0 -0
- data/test/data/images/truecolour-alpha-8bit.png +0 -0
- data/test/data/images/truecolour-gama-chrm-8bit.png +0 -0
- data/test/data/images/truecolour-srgb-8bit.png +0 -0
- data/test/data/minimal.pdf +44 -0
- data/test/data/standard-security-handler/README +9 -0
- data/test/data/standard-security-handler/bothpwd-aes-128bit-V4.pdf +44 -0
- data/test/data/standard-security-handler/bothpwd-aes-256bit-V5.pdf +0 -0
- data/test/data/standard-security-handler/bothpwd-arc4-128bit-V2.pdf +43 -0
- data/test/data/standard-security-handler/bothpwd-arc4-128bit-V4.pdf +43 -0
- data/test/data/standard-security-handler/bothpwd-arc4-40bit-V1.pdf +0 -0
- data/test/data/standard-security-handler/nopwd-aes-128bit-V4.pdf +43 -0
- data/test/data/standard-security-handler/nopwd-aes-256bit-V5.pdf +0 -0
- data/test/data/standard-security-handler/nopwd-arc4-128bit-V2.pdf +43 -0
- data/test/data/standard-security-handler/nopwd-arc4-128bit-V4.pdf +43 -0
- data/test/data/standard-security-handler/nopwd-arc4-40bit-V1.pdf +43 -0
- data/test/data/standard-security-handler/ownerpwd-aes-128bit-V4.pdf +0 -0
- data/test/data/standard-security-handler/ownerpwd-aes-256bit-V5.pdf +43 -0
- data/test/data/standard-security-handler/ownerpwd-arc4-128bit-V2.pdf +43 -0
- data/test/data/standard-security-handler/ownerpwd-arc4-128bit-V4.pdf +43 -0
- data/test/data/standard-security-handler/ownerpwd-arc4-40bit-V1.pdf +43 -0
- data/test/data/standard-security-handler/userpwd-aes-128bit-V4.pdf +43 -0
- data/test/data/standard-security-handler/userpwd-aes-256bit-V5.pdf +43 -0
- data/test/data/standard-security-handler/userpwd-arc4-128bit-V2.pdf +0 -0
- data/test/data/standard-security-handler/userpwd-arc4-128bit-V4.pdf +0 -0
- data/test/data/standard-security-handler/userpwd-arc4-40bit-V1.pdf +43 -0
- data/test/hexapdf/common_tokenizer_tests.rb +204 -0
- data/test/hexapdf/content/common.rb +31 -0
- data/test/hexapdf/content/graphic_object/test_arc.rb +93 -0
- data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +91 -0
- data/test/hexapdf/content/graphic_object/test_solid_arc.rb +86 -0
- data/test/hexapdf/content/test_canvas.rb +1113 -0
- data/test/hexapdf/content/test_color_space.rb +97 -0
- data/test/hexapdf/content/test_graphics_state.rb +138 -0
- data/test/hexapdf/content/test_operator.rb +619 -0
- data/test/hexapdf/content/test_parser.rb +66 -0
- data/test/hexapdf/content/test_processor.rb +156 -0
- data/test/hexapdf/content/test_transformation_matrix.rb +64 -0
- data/test/hexapdf/encryption/common.rb +87 -0
- data/test/hexapdf/encryption/test_aes.rb +121 -0
- data/test/hexapdf/encryption/test_arc4.rb +39 -0
- data/test/hexapdf/encryption/test_fast_aes.rb +17 -0
- data/test/hexapdf/encryption/test_fast_arc4.rb +12 -0
- data/test/hexapdf/encryption/test_identity.rb +21 -0
- data/test/hexapdf/encryption/test_ruby_aes.rb +23 -0
- data/test/hexapdf/encryption/test_ruby_arc4.rb +20 -0
- data/test/hexapdf/encryption/test_security_handler.rb +356 -0
- data/test/hexapdf/encryption/test_standard_security_handler.rb +274 -0
- data/test/hexapdf/filter/common.rb +53 -0
- data/test/hexapdf/filter/test_ascii85_decode.rb +60 -0
- data/test/hexapdf/filter/test_ascii_hex_decode.rb +33 -0
- data/test/hexapdf/filter/test_encryption.rb +24 -0
- data/test/hexapdf/filter/test_flate_decode.rb +35 -0
- data/test/hexapdf/filter/test_lzw_decode.rb +52 -0
- data/test/hexapdf/filter/test_predictor.rb +183 -0
- data/test/hexapdf/filter/test_run_length_decode.rb +32 -0
- data/test/hexapdf/font/cmap/test_parser.rb +67 -0
- data/test/hexapdf/font/cmap/test_writer.rb +58 -0
- data/test/hexapdf/font/encoding/test_base.rb +35 -0
- data/test/hexapdf/font/encoding/test_difference_encoding.rb +21 -0
- data/test/hexapdf/font/encoding/test_glyph_list.rb +59 -0
- data/test/hexapdf/font/encoding/test_zapf_dingbats_encoding.rb +16 -0
- data/test/hexapdf/font/test_encoding.rb +27 -0
- data/test/hexapdf/font/test_true_type_wrapper.rb +110 -0
- data/test/hexapdf/font/test_type1_wrapper.rb +66 -0
- data/test/hexapdf/font/true_type/common.rb +19 -0
- data/test/hexapdf/font/true_type/table/test_cmap.rb +59 -0
- data/test/hexapdf/font/true_type/table/test_cmap_subtable.rb +133 -0
- data/test/hexapdf/font/true_type/table/test_directory.rb +35 -0
- data/test/hexapdf/font/true_type/table/test_glyf.rb +58 -0
- data/test/hexapdf/font/true_type/table/test_head.rb +76 -0
- data/test/hexapdf/font/true_type/table/test_hhea.rb +40 -0
- data/test/hexapdf/font/true_type/table/test_hmtx.rb +38 -0
- data/test/hexapdf/font/true_type/table/test_loca.rb +43 -0
- data/test/hexapdf/font/true_type/table/test_maxp.rb +62 -0
- data/test/hexapdf/font/true_type/table/test_name.rb +95 -0
- data/test/hexapdf/font/true_type/table/test_os2.rb +65 -0
- data/test/hexapdf/font/true_type/table/test_post.rb +89 -0
- data/test/hexapdf/font/true_type/test_font.rb +120 -0
- data/test/hexapdf/font/true_type/test_table.rb +41 -0
- data/test/hexapdf/font/type1/test_afm_parser.rb +51 -0
- data/test/hexapdf/font/type1/test_font.rb +68 -0
- data/test/hexapdf/font/type1/test_pfb_parser.rb +37 -0
- data/test/hexapdf/font_loader/test_from_configuration.rb +28 -0
- data/test/hexapdf/font_loader/test_standard14.rb +22 -0
- data/test/hexapdf/image_loader/test_jpeg.rb +83 -0
- data/test/hexapdf/image_loader/test_pdf.rb +47 -0
- data/test/hexapdf/image_loader/test_png.rb +258 -0
- data/test/hexapdf/task/test_dereference.rb +46 -0
- data/test/hexapdf/task/test_optimize.rb +137 -0
- data/test/hexapdf/test_configuration.rb +82 -0
- data/test/hexapdf/test_data_dir.rb +32 -0
- data/test/hexapdf/test_dictionary.rb +284 -0
- data/test/hexapdf/test_dictionary_fields.rb +185 -0
- data/test/hexapdf/test_document.rb +574 -0
- data/test/hexapdf/test_document_utils.rb +144 -0
- data/test/hexapdf/test_filter.rb +96 -0
- data/test/hexapdf/test_font_utils.rb +47 -0
- data/test/hexapdf/test_importer.rb +78 -0
- data/test/hexapdf/test_object.rb +177 -0
- data/test/hexapdf/test_parser.rb +394 -0
- data/test/hexapdf/test_rectangle.rb +36 -0
- data/test/hexapdf/test_reference.rb +41 -0
- data/test/hexapdf/test_revision.rb +139 -0
- data/test/hexapdf/test_revisions.rb +93 -0
- data/test/hexapdf/test_serializer.rb +169 -0
- data/test/hexapdf/test_stream.rb +262 -0
- data/test/hexapdf/test_tokenizer.rb +30 -0
- data/test/hexapdf/test_writer.rb +120 -0
- data/test/hexapdf/test_xref_section.rb +35 -0
- data/test/hexapdf/type/test_catalog.rb +30 -0
- data/test/hexapdf/type/test_embedded_file.rb +16 -0
- data/test/hexapdf/type/test_file_specification.rb +148 -0
- data/test/hexapdf/type/test_font.rb +35 -0
- data/test/hexapdf/type/test_font_descriptor.rb +51 -0
- data/test/hexapdf/type/test_font_simple.rb +190 -0
- data/test/hexapdf/type/test_font_type1.rb +128 -0
- data/test/hexapdf/type/test_form.rb +60 -0
- data/test/hexapdf/type/test_info.rb +14 -0
- data/test/hexapdf/type/test_names.rb +9 -0
- data/test/hexapdf/type/test_object_stream.rb +84 -0
- data/test/hexapdf/type/test_page.rb +260 -0
- data/test/hexapdf/type/test_page_tree_node.rb +255 -0
- data/test/hexapdf/type/test_resources.rb +167 -0
- data/test/hexapdf/type/test_trailer.rb +109 -0
- data/test/hexapdf/type/test_xref_stream.rb +131 -0
- data/test/hexapdf/utils/test_bit_field.rb +47 -0
- data/test/hexapdf/utils/test_lru_cache.rb +22 -0
- data/test/hexapdf/utils/test_object_hash.rb +115 -0
- data/test/hexapdf/utils/test_pdf_doc_encoding.rb +18 -0
- data/test/hexapdf/utils/test_sorted_tree_node.rb +232 -0
- data/test/test_helper.rb +56 -0
- metadata +427 -0
@@ -0,0 +1,579 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# This file is part of HexaPDF.
|
5
|
+
#
|
6
|
+
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
+
# Copyright (C) 2016 Thomas Leitner
|
8
|
+
#
|
9
|
+
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
|
+
# under the terms of the GNU Affero General Public License version 3 as
|
11
|
+
# published by the Free Software Foundation with the addition of the
|
12
|
+
# following permission added to Section 15 as permitted in Section 7(a):
|
13
|
+
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
|
14
|
+
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
|
15
|
+
# INFRINGEMENT OF THIRD PARTY RIGHTS.
|
16
|
+
#
|
17
|
+
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
|
18
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
20
|
+
# License for more details.
|
21
|
+
#
|
22
|
+
# You should have received a copy of the GNU Affero General Public License
|
23
|
+
# along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
|
24
|
+
#
|
25
|
+
# The interactive user interfaces in modified source and object code
|
26
|
+
# versions of HexaPDF must display Appropriate Legal Notices, as required
|
27
|
+
# under Section 5 of the GNU Affero General Public License version 3.
|
28
|
+
#
|
29
|
+
# In accordance with Section 7(b) of the GNU Affero General Public
|
30
|
+
# License, a covered work must retain the producer line in every PDF that
|
31
|
+
# is created or manipulated using HexaPDF.
|
32
|
+
#++
|
33
|
+
|
34
|
+
require 'hexapdf/error'
|
35
|
+
require 'hexapdf/configuration'
|
36
|
+
require 'hexapdf/content/color_space'
|
37
|
+
require 'hexapdf/content/transformation_matrix'
|
38
|
+
|
39
|
+
module HexaPDF
|
40
|
+
module Content
|
41
|
+
|
42
|
+
# Associates a name with a value, used by various graphics state parameters.
|
43
|
+
class NamedValue
|
44
|
+
|
45
|
+
# The value itself.
|
46
|
+
attr_reader :value
|
47
|
+
|
48
|
+
# The name for the value.
|
49
|
+
attr_reader :name
|
50
|
+
|
51
|
+
# Creates a new NamedValue object and freezes it.
|
52
|
+
def initialize(name, value)
|
53
|
+
@name = name
|
54
|
+
@value = value
|
55
|
+
freeze
|
56
|
+
end
|
57
|
+
|
58
|
+
# The object is equal to +other+ if either the name or the value is equal to +other+, or if
|
59
|
+
# the other object is a NamedValue object with the same name and value.
|
60
|
+
def ==(other)
|
61
|
+
@name == other || @value == other ||
|
62
|
+
(other.kind_of?(NamedValue) && @name == other.name && @value == other.value)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the value.
|
66
|
+
def to_operands
|
67
|
+
@value
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
# Defines all available line cap styles as constants. Each line cap style is an instance of
|
74
|
+
# NamedValue. For use with Content::GraphicsState#line_cap_style.
|
75
|
+
#
|
76
|
+
# See: PDF1.7 s8.4.3.3
|
77
|
+
module LineCapStyle
|
78
|
+
|
79
|
+
# Returns the argument normalized to a valid line cap style.
|
80
|
+
#
|
81
|
+
# * 0 or +:butt+ can be used for the BUTT_CAP style.
|
82
|
+
# * 1 or +:round+ can be used for the ROUND_CAP style.
|
83
|
+
# * 2 or +:projecting_square+ can be used for the PROJECTING_SQUARE_CAP style.
|
84
|
+
# * Otherwise an error is raised.
|
85
|
+
def self.normalize(style)
|
86
|
+
case style
|
87
|
+
when :butt, 0 then BUTT_CAP
|
88
|
+
when :round, 1 then ROUND_CAP
|
89
|
+
when :projecting_square, 2 then PROJECTING_SQUARE_CAP
|
90
|
+
else
|
91
|
+
raise ArgumentError, "Unknown line cap style: #{style}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Stroke is squared off at the endpoint of a path.
|
96
|
+
BUTT_CAP = NamedValue.new(:butt, 0)
|
97
|
+
|
98
|
+
# A semicircular arc is drawn at the endpoint of a path.
|
99
|
+
ROUND_CAP = NamedValue.new(:round, 1)
|
100
|
+
|
101
|
+
# The stroke continues half the line width beyond the endpoint of a path.
|
102
|
+
PROJECTING_SQUARE_CAP = NamedValue.new(:projecting_square, 2)
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
# Defines all available line join styles as constants. Each line join style is an instance of
|
108
|
+
# NamedValue. For use with Content::GraphicsState#line_join_style.
|
109
|
+
#
|
110
|
+
# See: PDF1.7 s8.4.3.4
|
111
|
+
module LineJoinStyle
|
112
|
+
|
113
|
+
# Returns the argument normalized to a valid line join style.
|
114
|
+
#
|
115
|
+
# * 0 or +:miter+ can be used for the MITER_JOIN style.
|
116
|
+
# * 1 or +:round+ can be used for the ROUND_JOIN style.
|
117
|
+
# * 2 or +:bevel+ can be used for the BEVEL_JOIN style.
|
118
|
+
# * Otherwise an error is raised.
|
119
|
+
def self.normalize(style)
|
120
|
+
case style
|
121
|
+
when :miter, 0 then MITER_JOIN
|
122
|
+
when :round, 1 then ROUND_JOIN
|
123
|
+
when :bevel, 2 then BEVEL_JOIN
|
124
|
+
else
|
125
|
+
raise ArgumentError, "Unknown line join style: #{style}"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# The outer lines of the two segments continue until the meet at an angle.
|
130
|
+
MITER_JOIN = NamedValue.new(:miter, 0)
|
131
|
+
|
132
|
+
# An arc of a circle is drawn around the point where the segments meet.
|
133
|
+
ROUND_JOIN = NamedValue.new(:round, 1)
|
134
|
+
|
135
|
+
# The two segments are finished with butt caps and the space between the ends is filled with
|
136
|
+
# a triangle.
|
137
|
+
BEVEL_JOIN = NamedValue.new(:bevel, 2)
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
# The line dash pattern defines how a line should be dashed. For use with
|
143
|
+
# Content::GraphicsState#line_dash_pattern.
|
144
|
+
#
|
145
|
+
# A dash pattern consists of two parts: the dash array and the dash phase. The dash array
|
146
|
+
# defines the length of alternating dashes and gaps (important: starting with dashes). And the
|
147
|
+
# dash phase defines the distance into the dash array at which to start.
|
148
|
+
#
|
149
|
+
# It is easier to show. Following are dash arrays and dash phases and how they would be
|
150
|
+
# interpreted:
|
151
|
+
#
|
152
|
+
# [] 0 No dash, one solid line
|
153
|
+
# [3] 0 3 unit dash, 3 unit gap, 3 unit dash, 3 unit gap, ...
|
154
|
+
# [3] 1 2 unit dash, 3 unit gap, 3 unit dash, 3 unit gap, ...
|
155
|
+
# [2 1] 0 2 unit dash, 1 unit gap, 2 unit dash, 1 unit gap, ...
|
156
|
+
# [3 5] 6 2 unit gap, 3 unit dash, 5 unit gap, 3 unit dash, ...
|
157
|
+
# [2 3] 6 1 unit dash, 3 unit gap, 2 unit dash, 3 unit gap, ...
|
158
|
+
#
|
159
|
+
# See: PDF1.7 s8.4.3.6
|
160
|
+
class LineDashPattern
|
161
|
+
|
162
|
+
# The dash array.
|
163
|
+
attr_reader :array
|
164
|
+
|
165
|
+
# The dash phase.
|
166
|
+
attr_reader :phase
|
167
|
+
|
168
|
+
# Inititalizes the line dash pattern with the given +array+ and +phase+.
|
169
|
+
#
|
170
|
+
# The argument +phase+ must be non-negative and the numbers in the +array+ must be
|
171
|
+
# non-negative and must not all be zero.
|
172
|
+
def initialize(array = [], phase = 0)
|
173
|
+
if phase < 0 || (!array.empty? &&
|
174
|
+
array.inject(0) {|m, n| m < 0 ? m : (n < 0 ? -1 : m + n)} <= 0)
|
175
|
+
raise ArgumentError, "Invalid line dash pattern: #{array.inspect} #{phase.inspect}"
|
176
|
+
end
|
177
|
+
@array = array.freeze
|
178
|
+
@phase = phase
|
179
|
+
end
|
180
|
+
|
181
|
+
# Returns +true+ if the other line dash pattern is the same as this one.
|
182
|
+
def ==(other)
|
183
|
+
other.kind_of?(self.class) && other.array == array && other.phase == phase
|
184
|
+
end
|
185
|
+
|
186
|
+
# Converts the LineDashPattern object to an array of operands for the associated PDF content
|
187
|
+
# operator.
|
188
|
+
def to_operands
|
189
|
+
[@array, @phase]
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
# Defines all available rendering intents as constants. For use with
|
196
|
+
# Content::GraphicsState#rendering_intent.
|
197
|
+
#
|
198
|
+
# See: PDF1.7 s8.6.5.8
|
199
|
+
module RenderingIntent
|
200
|
+
|
201
|
+
# Returns the argument normalized to a valid rendering intent.
|
202
|
+
#
|
203
|
+
# * If the argument is a valid symbol, it is just returned.
|
204
|
+
# * Otherwise an error is raised.
|
205
|
+
def self.normalize(intent)
|
206
|
+
case intent
|
207
|
+
when ABSOLUTE_COLORIMETRIC, RELATIVE_COLORIMETRIC, SATURATION, PERCEPTUAL
|
208
|
+
intent
|
209
|
+
else
|
210
|
+
raise ArgumentError, "Invalid rendering intent: #{intent}"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# Colors should be represented solely with respect to the light source.
|
215
|
+
ABSOLUTE_COLORIMETRIC = :AbsoluteColorimetric
|
216
|
+
|
217
|
+
# Colous should be represented with respect to the combination of the light source and the
|
218
|
+
# output medium's white point.
|
219
|
+
RELATIVE_COLORIMETRIC = :RelativeColorimetric
|
220
|
+
|
221
|
+
# Colors should be represented in a manner that preserves or emphasizes saturation.
|
222
|
+
SATURATION = :Saturation
|
223
|
+
|
224
|
+
# Colous should be represented in a manner that provides a pleasing perceptual appearance.
|
225
|
+
PERCEPTUAL = :Perceptual
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
|
230
|
+
# Defines all available text rendering modes as constants. Each text rendering mode is an
|
231
|
+
# instance of NamedValue. For use with Content::GraphicsState#text_rendering_mode.
|
232
|
+
#
|
233
|
+
# See: PDF1.7 s9.3.6
|
234
|
+
module TextRenderingMode
|
235
|
+
|
236
|
+
# Returns the argument normalized to a valid text rendering mode.
|
237
|
+
#
|
238
|
+
# * 0 or +:fill+ can be used for the FILL mode.
|
239
|
+
# * 1 or +:stroke+ can be used for the STROKE mode.
|
240
|
+
# * 2 or +:fill_stroke+ can be used for the FILL_STROKE mode.
|
241
|
+
# * 3 or +:invisible+ can be used for the INVISIBLE mode.
|
242
|
+
# * 4 or +:fill_clip+ can be used for the FILL_CLIP mode.
|
243
|
+
# * 5 or +:stroke_clip+ can be used for the STROKE_CLIP mode.
|
244
|
+
# * 6 or +:fill_stroke_clip+ can be used for the FILL_STROKE_CLIP mode.
|
245
|
+
# * 7 or +:clip+ can be used for the CLIP mode.
|
246
|
+
# * Otherwise an error is raised.
|
247
|
+
def self.normalize(style)
|
248
|
+
case style
|
249
|
+
when :fill, 0 then FILL
|
250
|
+
when :stroke, 1 then STROKE
|
251
|
+
when :fill_stroke, 2 then FILL_STROKE
|
252
|
+
when :invisible, 3 then INVISIBLE
|
253
|
+
when :fill_clip, 4 then FILL_CLIP
|
254
|
+
when :stroke_clip, 5 then STROKE_CLIP
|
255
|
+
when :fill_stroke_clip, 6 then FILL_STROKE_CLIP
|
256
|
+
when :clip, 7 then CLIP
|
257
|
+
else
|
258
|
+
raise ArgumentError, "Unknown text rendering mode: #{style}"
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# Fill text
|
263
|
+
FILL = NamedValue.new(:fill, 0)
|
264
|
+
|
265
|
+
# Stroke text
|
266
|
+
STROKE = NamedValue.new(:stroke, 1)
|
267
|
+
|
268
|
+
# Fill, then stroke text
|
269
|
+
FILL_STROKE = NamedValue.new(:fill_stroke, 2)
|
270
|
+
|
271
|
+
# Neither fill nor stroke text (invisible)
|
272
|
+
INVISIBLE = NamedValue.new(:invisible, 3)
|
273
|
+
|
274
|
+
# Fill text and add to path for clipping
|
275
|
+
FILL_CLIP = NamedValue.new(:fill_clip, 4)
|
276
|
+
|
277
|
+
# Stroke text and add to path for clipping
|
278
|
+
STROKE_CLIP = NamedValue.new(:stroke_clip, 5)
|
279
|
+
|
280
|
+
# Fill, then stroke text and add to path for clipping
|
281
|
+
FILL_STROKE_CLIP = NamedValue.new(:fill_stroke_clip, 6)
|
282
|
+
|
283
|
+
# Add text to path for clipping
|
284
|
+
CLIP = NamedValue.new(:clip, 7)
|
285
|
+
|
286
|
+
end
|
287
|
+
|
288
|
+
|
289
|
+
# A GraphicsState object holds all the graphic control parameters needed for correct
|
290
|
+
# operation when parsing or creating a content stream with a Processor object.
|
291
|
+
#
|
292
|
+
# While a content stream is parsed/created, operations may use the current parameters or
|
293
|
+
# modify them.
|
294
|
+
#
|
295
|
+
# The device-dependent graphics state parameters have not been implemented!
|
296
|
+
#
|
297
|
+
# See: PDF1.7 s8.4.1
|
298
|
+
class GraphicsState
|
299
|
+
|
300
|
+
# The current transformation matrix.
|
301
|
+
attr_accessor :ctm
|
302
|
+
|
303
|
+
# The current color used for stroking operations during painting.
|
304
|
+
attr_accessor :stroke_color
|
305
|
+
|
306
|
+
# The current color used for all other (i.e. non-stroking) painting operations.
|
307
|
+
attr_accessor :fill_color
|
308
|
+
|
309
|
+
# The current line width in user space units.
|
310
|
+
attr_accessor :line_width
|
311
|
+
|
312
|
+
# The current line cap style (for the available values see LineCapStyle).
|
313
|
+
attr_accessor :line_cap_style
|
314
|
+
|
315
|
+
# The current line join style (for the available values see LineJoinStyle).
|
316
|
+
attr_accessor :line_join_style
|
317
|
+
|
318
|
+
# The maximum line length of mitered line joins for stroked paths.
|
319
|
+
attr_accessor :miter_limit
|
320
|
+
|
321
|
+
# The line dash pattern (see LineDashPattern).
|
322
|
+
attr_accessor :line_dash_pattern
|
323
|
+
|
324
|
+
# The rendering intent (only used for CIE-based colors; for the available values see
|
325
|
+
# RenderingIntent).
|
326
|
+
attr_accessor :rendering_intent
|
327
|
+
|
328
|
+
# The stroke adjustment for very small line width.
|
329
|
+
attr_accessor :stroke_adjustment
|
330
|
+
|
331
|
+
# The current blend mode for the transparent imaging model.
|
332
|
+
attr_accessor :blend_mode
|
333
|
+
|
334
|
+
# The soft mask specifying the mask shape or mask opacity value to be used in the
|
335
|
+
# transparent imaging model.
|
336
|
+
attr_accessor :soft_mask
|
337
|
+
|
338
|
+
# The alpha constant for stroking operations in the transparent imaging model.
|
339
|
+
attr_accessor :stroke_alpha
|
340
|
+
|
341
|
+
# The alpha constant for non-stroking operations in the transparent imaging model.
|
342
|
+
attr_accessor :fill_alpha
|
343
|
+
|
344
|
+
# A boolean specifying whether the current soft mask and alpha parameters should be
|
345
|
+
# interpreted as shape values or opacity values.
|
346
|
+
attr_accessor :alpha_source
|
347
|
+
|
348
|
+
|
349
|
+
# The text matrix.
|
350
|
+
#
|
351
|
+
# This attribute is non-nil only when inside a text object.
|
352
|
+
attr_accessor :tm
|
353
|
+
|
354
|
+
# The text line matrix which captures the state of the text matrix at the beginning of a line.
|
355
|
+
#
|
356
|
+
# As with the text matrix the text line matrix is non-nil only when inside a text object.
|
357
|
+
attr_accessor :tlm
|
358
|
+
|
359
|
+
# The character spacing in unscaled text units.
|
360
|
+
#
|
361
|
+
# It specifies the additional spacing used for the horizontal or vertical displacement of
|
362
|
+
# glyphs.
|
363
|
+
attr_reader :character_spacing
|
364
|
+
|
365
|
+
# The word spacing in unscaled text units.
|
366
|
+
#
|
367
|
+
# It works like the character spacing but is only applied to the ASCII space character.
|
368
|
+
attr_reader :word_spacing
|
369
|
+
|
370
|
+
# The horizontal text scaling.
|
371
|
+
#
|
372
|
+
# The value specifies the percentage of the normal width that should be used.
|
373
|
+
attr_reader :horizontal_scaling
|
374
|
+
|
375
|
+
# The leading in unscaled text units.
|
376
|
+
#
|
377
|
+
# It specifies the distance between the baselines of adjacent lines of text.
|
378
|
+
attr_accessor :leading
|
379
|
+
|
380
|
+
# The font for the text.
|
381
|
+
attr_accessor :font
|
382
|
+
|
383
|
+
# The font size.
|
384
|
+
attr_reader :font_size
|
385
|
+
|
386
|
+
# The text rendering mode.
|
387
|
+
#
|
388
|
+
# It determines if and how the glyphs of a text should be shown (for all available values
|
389
|
+
# see TextRenderingMode).
|
390
|
+
attr_accessor :text_rendering_mode
|
391
|
+
|
392
|
+
# The text rise distance in unscaled text units.
|
393
|
+
#
|
394
|
+
# It specifies the distance that the baseline should be moved up or down from its default
|
395
|
+
# location.
|
396
|
+
attr_accessor :text_rise
|
397
|
+
|
398
|
+
# The text knockout, a boolean value.
|
399
|
+
#
|
400
|
+
# It specifies whether each glyph should be treated as separate elementary object for the
|
401
|
+
# purpose of color compositing in the transparent imaging model (knockout = +false+) or if
|
402
|
+
# all glyphs together are treated as one elementary object (knockout = +true+).
|
403
|
+
attr_accessor :text_knockout
|
404
|
+
|
405
|
+
|
406
|
+
# The scaled character spacing used in glyph displacement calculations.
|
407
|
+
#
|
408
|
+
# This returns the value T_c multiplied by #scaled_horizontal_scaling.
|
409
|
+
#
|
410
|
+
# See PDF1.7 s9.4.4
|
411
|
+
attr_reader :scaled_character_spacing
|
412
|
+
|
413
|
+
# The scaled word spacing used in glyph displacement calculations.
|
414
|
+
#
|
415
|
+
# This returns the value T_w multiplied by #scaled_horizontal_scaling.
|
416
|
+
#
|
417
|
+
# See PDF1.7 s9.4.4
|
418
|
+
attr_reader :scaled_word_spacing
|
419
|
+
|
420
|
+
# The scaled font size used in glyph displacement calculations.
|
421
|
+
#
|
422
|
+
# This returns the value T_fs / 1000 multiplied by #scaled_horizontal_scaling.
|
423
|
+
#
|
424
|
+
# See PDF1.7 s9.4.4
|
425
|
+
attr_reader :scaled_font_size
|
426
|
+
|
427
|
+
# The scaled horizontal scaling used in glyph displacement calculations.
|
428
|
+
#
|
429
|
+
# Since the horizontal scaling attribute is stored in percent of 100, this method returns the
|
430
|
+
# correct value for calculations.
|
431
|
+
#
|
432
|
+
# See PDF1.7 s9.4.4
|
433
|
+
attr_reader :scaled_horizontal_scaling
|
434
|
+
|
435
|
+
|
436
|
+
# Initializes the graphics state parameters to their default values.
|
437
|
+
def initialize
|
438
|
+
@ctm = TransformationMatrix.new
|
439
|
+
@stroke_color = @fill_color =
|
440
|
+
GlobalConfiguration.constantize('color_space.map'.freeze, :DeviceGray).new.default_color
|
441
|
+
@line_width = 1.0
|
442
|
+
@line_cap_style = LineCapStyle::BUTT_CAP
|
443
|
+
@line_join_style = LineJoinStyle::MITER_JOIN
|
444
|
+
@miter_limit = 10.0
|
445
|
+
@line_dash_pattern = LineDashPattern.new
|
446
|
+
@rendering_intent = RenderingIntent::RELATIVE_COLORIMETRIC
|
447
|
+
@stroke_adjustment = false
|
448
|
+
@blend_mode = :Normal
|
449
|
+
@soft_mask = :None
|
450
|
+
@stroke_alpha = @fill_alpha = 1.0
|
451
|
+
@alpha_source = false
|
452
|
+
|
453
|
+
@tm = nil
|
454
|
+
@tlm = nil
|
455
|
+
@character_spacing = 0
|
456
|
+
@word_spacing = 0
|
457
|
+
@horizontal_scaling = 100
|
458
|
+
@leading = 0
|
459
|
+
@font = nil
|
460
|
+
@font_size = 0
|
461
|
+
@text_rendering_mode = TextRenderingMode::FILL
|
462
|
+
@text_rise = 0
|
463
|
+
@text_knockout = true
|
464
|
+
|
465
|
+
@scaled_character_spacing = 0
|
466
|
+
@scaled_word_spacing = 0
|
467
|
+
@scaled_font_size = 0
|
468
|
+
@scaled_horizontal_scaling = 1
|
469
|
+
|
470
|
+
@stack = []
|
471
|
+
end
|
472
|
+
|
473
|
+
# Saves the current graphics state on the internal stack.
|
474
|
+
def save
|
475
|
+
@stack.push([@ctm, @stroke_color, @fill_color,
|
476
|
+
@line_width, @line_cap_style, @line_join_style, @miter_limit,
|
477
|
+
@line_dash_pattern, @rendering_intent, @stroke_adjustment, @blend_mode,
|
478
|
+
@soft_mask, @stroke_alpha, @fill_alpha, @alpha_source,
|
479
|
+
@character_spacing, @word_spacing, @horizontal_scaling, @leading,
|
480
|
+
@font, @font_size, @text_rendering_mode, @text_rise, @text_knockout,
|
481
|
+
@scaled_character_spacing, @scaled_word_spacing, @scaled_font_size,
|
482
|
+
@scaled_horizontal_scaling])
|
483
|
+
@ctm = @ctm.dup
|
484
|
+
end
|
485
|
+
|
486
|
+
# Restores the graphics state from the internal stack.
|
487
|
+
#
|
488
|
+
# Raises an error if the stack is empty.
|
489
|
+
def restore
|
490
|
+
if @stack.empty?
|
491
|
+
raise HexaPDF::Error, "Can't restore graphics state because the stack is empty"
|
492
|
+
end
|
493
|
+
@ctm, @stroke_color, @fill_color,
|
494
|
+
@line_width, @line_cap_style, @line_join_style, @miter_limit, @line_dash_pattern,
|
495
|
+
@rendering_intent, @stroke_adjustment, @blend_mode,
|
496
|
+
@soft_mask, @stroke_alpha, @fill_alpha, @alpha_source,
|
497
|
+
@character_spacing, @word_spacing, @horizontal_scaling, @leading,
|
498
|
+
@font, @font_size, @text_rendering_mode, @text_rise, @text_knockout,
|
499
|
+
@scaled_character_spacing, @scaled_word_spacing, @scaled_font_size,
|
500
|
+
@scaled_horizontal_scaling = @stack.pop
|
501
|
+
end
|
502
|
+
|
503
|
+
# Returns +true+ if the internal stack of saved graphic states contains entries.
|
504
|
+
def saved_states?
|
505
|
+
!@stack.empty?
|
506
|
+
end
|
507
|
+
|
508
|
+
##
|
509
|
+
# :attr_accessor: stroke_color_space
|
510
|
+
#
|
511
|
+
# The current color space for stroking operations during painting.
|
512
|
+
|
513
|
+
# :nodoc:
|
514
|
+
def stroke_color_space
|
515
|
+
@stroke_color.color_space
|
516
|
+
end
|
517
|
+
|
518
|
+
def stroke_color_space=(color_space) # :nodoc:
|
519
|
+
self.stroke_color = color_space.default_color
|
520
|
+
end
|
521
|
+
|
522
|
+
##
|
523
|
+
# :attr_accessor: fill_color_space
|
524
|
+
#
|
525
|
+
# The current color space for non-stroking operations during painting.
|
526
|
+
|
527
|
+
# :nodoc:
|
528
|
+
def fill_color_space
|
529
|
+
@fill_color.color_space
|
530
|
+
end
|
531
|
+
|
532
|
+
def fill_color_space=(color_space) #:nodoc:
|
533
|
+
self.fill_color = color_space.default_color
|
534
|
+
end
|
535
|
+
|
536
|
+
##
|
537
|
+
# :attr_writer: character_spacing
|
538
|
+
#
|
539
|
+
# Sets the character spacing and updates the scaled character spacing.
|
540
|
+
def character_spacing=(space)
|
541
|
+
@character_spacing = space
|
542
|
+
@scaled_character_spacing = space * @scaled_horizontal_scaling
|
543
|
+
end
|
544
|
+
|
545
|
+
##
|
546
|
+
# :attr_writer: word_spacing
|
547
|
+
#
|
548
|
+
# Sets the word spacing and updates the scaled word spacing.
|
549
|
+
def word_spacing=(space)
|
550
|
+
@word_spacing = space
|
551
|
+
@scaled_word_spacing = space * @scaled_horizontal_scaling
|
552
|
+
end
|
553
|
+
|
554
|
+
##
|
555
|
+
# :attr_writer: font_size
|
556
|
+
#
|
557
|
+
# Sets the font size and updates the scaled font size.
|
558
|
+
def font_size=(size)
|
559
|
+
@font_size = size
|
560
|
+
@scaled_font_size = size / 1000.0 * @scaled_horizontal_scaling
|
561
|
+
end
|
562
|
+
|
563
|
+
##
|
564
|
+
# :attr_writer: horizontal_scaling
|
565
|
+
#
|
566
|
+
# Sets the horizontal scaling and updates the scaled character spacing, scaled word spacing
|
567
|
+
# and scaled font size.
|
568
|
+
def horizontal_scaling=(scaling)
|
569
|
+
@horizontal_scaling = scaling
|
570
|
+
@scaled_horizontal_scaling = scaling / 100.0
|
571
|
+
@scaled_character_spacing = @character_spacing * @scaled_horizontal_scaling
|
572
|
+
@scaled_word_spacing = @word_spacing * @scaled_horizontal_scaling
|
573
|
+
@scaled_font_size = @font_size / 1000.0 * @scaled_horizontal_scaling
|
574
|
+
end
|
575
|
+
|
576
|
+
end
|
577
|
+
|
578
|
+
end
|
579
|
+
end
|