hexapdf 1.1.1 → 1.3.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/CHANGELOG.md +79 -0
- data/README.md +1 -1
- data/lib/hexapdf/cli/command.rb +63 -63
- data/lib/hexapdf/cli/inspect.rb +14 -5
- data/lib/hexapdf/cli/modify.rb +0 -1
- data/lib/hexapdf/cli/optimize.rb +5 -5
- data/lib/hexapdf/composer.rb +14 -0
- data/lib/hexapdf/configuration.rb +26 -0
- data/lib/hexapdf/content/graphics_state.rb +1 -1
- data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +1 -1
- data/lib/hexapdf/document/annotations.rb +173 -0
- data/lib/hexapdf/document/layout.rb +45 -6
- data/lib/hexapdf/document.rb +28 -7
- data/lib/hexapdf/error.rb +11 -3
- data/lib/hexapdf/font/true_type/subsetter.rb +15 -2
- data/lib/hexapdf/font/true_type_wrapper.rb +1 -0
- data/lib/hexapdf/font/type1_wrapper.rb +1 -0
- data/lib/hexapdf/layout/style.rb +101 -7
- data/lib/hexapdf/object.rb +2 -2
- data/lib/hexapdf/pdf_array.rb +25 -3
- data/lib/hexapdf/tokenizer.rb +4 -1
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +57 -8
- data/lib/hexapdf/type/acro_form/field.rb +1 -0
- data/lib/hexapdf/type/acro_form/form.rb +7 -6
- data/lib/hexapdf/type/acro_form/java_script_actions.rb +9 -2
- data/lib/hexapdf/type/acro_form/text_field.rb +9 -2
- data/lib/hexapdf/type/annotation.rb +71 -1
- data/lib/hexapdf/type/annotations/appearance_generator.rb +348 -0
- data/lib/hexapdf/type/annotations/border_effect.rb +99 -0
- data/lib/hexapdf/type/annotations/border_styling.rb +160 -0
- data/lib/hexapdf/type/annotations/circle.rb +65 -0
- data/lib/hexapdf/type/annotations/interior_color.rb +84 -0
- data/lib/hexapdf/type/annotations/line.rb +490 -0
- data/lib/hexapdf/type/annotations/square.rb +65 -0
- data/lib/hexapdf/type/annotations/square_circle.rb +77 -0
- data/lib/hexapdf/type/annotations/widget.rb +52 -116
- data/lib/hexapdf/type/annotations.rb +8 -0
- data/lib/hexapdf/type/form.rb +2 -2
- data/lib/hexapdf/version.rb +1 -1
- data/lib/hexapdf/writer.rb +0 -1
- data/lib/hexapdf/xref_section.rb +7 -4
- data/test/hexapdf/content/test_graphics_state.rb +2 -3
- data/test/hexapdf/content/test_operator.rb +4 -5
- data/test/hexapdf/digital_signature/test_cms_handler.rb +7 -8
- data/test/hexapdf/digital_signature/test_handler.rb +2 -3
- data/test/hexapdf/digital_signature/test_pkcs1_handler.rb +1 -2
- data/test/hexapdf/document/test_annotations.rb +55 -0
- data/test/hexapdf/document/test_layout.rb +24 -2
- data/test/hexapdf/font/test_true_type_wrapper.rb +7 -0
- data/test/hexapdf/font/test_type1_wrapper.rb +7 -0
- data/test/hexapdf/font/true_type/test_subsetter.rb +10 -0
- data/test/hexapdf/layout/test_style.rb +27 -2
- data/test/hexapdf/task/test_optimize.rb +1 -1
- data/test/hexapdf/test_composer.rb +7 -0
- data/test/hexapdf/test_document.rb +11 -3
- data/test/hexapdf/test_object.rb +1 -1
- data/test/hexapdf/test_pdf_array.rb +36 -3
- data/test/hexapdf/test_stream.rb +1 -2
- data/test/hexapdf/test_xref_section.rb +1 -1
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +78 -3
- data/test/hexapdf/type/acro_form/test_button_field.rb +7 -6
- data/test/hexapdf/type/acro_form/test_field.rb +5 -0
- data/test/hexapdf/type/acro_form/test_form.rb +17 -1
- data/test/hexapdf/type/acro_form/test_java_script_actions.rb +21 -0
- data/test/hexapdf/type/acro_form/test_text_field.rb +7 -1
- data/test/hexapdf/type/annotations/test_appearance_generator.rb +482 -0
- data/test/hexapdf/type/annotations/test_border_effect.rb +59 -0
- data/test/hexapdf/type/annotations/test_border_styling.rb +114 -0
- data/test/hexapdf/type/annotations/test_interior_color.rb +37 -0
- data/test/hexapdf/type/annotations/test_line.rb +169 -0
- data/test/hexapdf/type/annotations/test_widget.rb +35 -81
- data/test/hexapdf/type/test_annotation.rb +55 -0
- data/test/hexapdf/type/test_form.rb +6 -0
- metadata +17 -2
| @@ -127,6 +127,13 @@ describe HexaPDF::Composer do | |
| 127 127 | 
             
                end
         | 
| 128 128 | 
             
              end
         | 
| 129 129 |  | 
| 130 | 
            +
              describe "style?" do
         | 
| 131 | 
            +
                it "delegates to layout.style?" do
         | 
| 132 | 
            +
                  @composer.document.layout.style(:header, font_size: 20)
         | 
| 133 | 
            +
                  assert(@composer.style?(:header))
         | 
| 134 | 
            +
                end
         | 
| 135 | 
            +
              end
         | 
| 136 | 
            +
             | 
| 130 137 | 
             
              describe "styles" do
         | 
| 131 138 | 
             
                it "delegates to layout.styles" do
         | 
| 132 139 | 
             
                  @composer.styles(base: {font_size: 30}, other: {font_size: 40})
         | 
| @@ -54,7 +54,7 @@ describe HexaPDF::Document do | |
| 54 54 | 
             
              describe "::open" do
         | 
| 55 55 | 
             
                before do
         | 
| 56 56 | 
             
                  @file = Tempfile.new('hexapdf-document')
         | 
| 57 | 
            -
                  @io_doc.write(@file)
         | 
| 57 | 
            +
                  @io_doc.write(@file, compact: false)
         | 
| 58 58 | 
             
                  @file.close
         | 
| 59 59 | 
             
                end
         | 
| 60 60 |  | 
| @@ -370,7 +370,7 @@ describe HexaPDF::Document do | |
| 370 370 | 
             
                it "writes the document to a file" do
         | 
| 371 371 | 
             
                  file = Tempfile.new('hexapdf-write')
         | 
| 372 372 | 
             
                  file.close
         | 
| 373 | 
            -
                  @io_doc.write(file.path)
         | 
| 373 | 
            +
                  @io_doc.write(file.path, compact: false)
         | 
| 374 374 | 
             
                  HexaPDF::Document.open(file.path) do |doc|
         | 
| 375 375 | 
             
                    assert_equal(200, doc.object(2).value)
         | 
| 376 376 | 
             
                  end
         | 
| @@ -422,10 +422,18 @@ describe HexaPDF::Document do | |
| 422 422 |  | 
| 423 423 | 
             
                it "allows optimizing the file by using object streams" do
         | 
| 424 424 | 
             
                  io = StringIO.new(''.b)
         | 
| 425 | 
            -
                  @io_doc.write(io, optimize: true)
         | 
| 425 | 
            +
                  @io_doc.write(io, optimize: true, compact: false)
         | 
| 426 426 | 
             
                  doc = HexaPDF::Document.new(io: io)
         | 
| 427 427 | 
             
                  assert_equal(2, doc.each.count {|o| o.type == :ObjStm })
         | 
| 428 428 | 
             
                end
         | 
| 429 | 
            +
             | 
| 430 | 
            +
                it "automatically compacts the file" do
         | 
| 431 | 
            +
                  io = StringIO.new(''.b)
         | 
| 432 | 
            +
                  @io_doc.write(io)
         | 
| 433 | 
            +
                  doc = HexaPDF::Document.new(io: io)
         | 
| 434 | 
            +
                  assert_equal(1, doc.revisions.count)
         | 
| 435 | 
            +
                  assert_equal(4, doc.each.count)
         | 
| 436 | 
            +
                end
         | 
| 429 437 | 
             
              end
         | 
| 430 438 |  | 
| 431 439 | 
             
              describe "version" do
         | 
    
        data/test/hexapdf/test_object.rb
    CHANGED
    
    | @@ -197,7 +197,7 @@ describe HexaPDF::Object do | |
| 197 197 | 
             
                  @obj.define_singleton_method(:perform_validation) { raise "Unknown" }
         | 
| 198 198 | 
             
                  invoked = []
         | 
| 199 199 | 
             
                  refute(@obj.validate {|*a| invoked << a })
         | 
| 200 | 
            -
                  assert_equal([[" | 
| 200 | 
            +
                  assert_equal([["Unexpected error encountered: Unknown", false, @obj]], invoked)
         | 
| 201 201 | 
             
                end
         | 
| 202 202 | 
             
              end
         | 
| 203 203 |  | 
| @@ -131,9 +131,42 @@ describe HexaPDF::PDFArray do | |
| 131 131 | 
             
                end
         | 
| 132 132 | 
             
              end
         | 
| 133 133 |  | 
| 134 | 
            -
               | 
| 135 | 
            -
                 | 
| 136 | 
            -
             | 
| 134 | 
            +
              describe "reject!" do
         | 
| 135 | 
            +
                it "allows deleting elements that are selected using a block" do
         | 
| 136 | 
            +
                  assert_same(@array, @array.reject! {|item| item == :data })
         | 
| 137 | 
            +
                  assert_equal([1, "deref", @array[2]], @array.to_a)
         | 
| 138 | 
            +
                end
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                it "returns nil if no elements were deleted" do
         | 
| 141 | 
            +
                  assert_nil(@array.reject! {|item| false })
         | 
| 142 | 
            +
                end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                it "returns an enumerator if no block is given" do
         | 
| 145 | 
            +
                  assert_kind_of(Enumerator, @array.reject!)
         | 
| 146 | 
            +
                end
         | 
| 147 | 
            +
              end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
              describe "map!" do
         | 
| 150 | 
            +
                it "maps elements in-place to the return values of the block" do
         | 
| 151 | 
            +
                  assert_same(@array, @array.map! {|item| 5 })
         | 
| 152 | 
            +
                  assert_equal([5, 5, 5, 5], @array.to_a)
         | 
| 153 | 
            +
                end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                it "returns an enumerator if no block is given" do
         | 
| 156 | 
            +
                  assert_kind_of(Enumerator, @array.reject!)
         | 
| 157 | 
            +
                end
         | 
| 158 | 
            +
              end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
              describe "compact!" do
         | 
| 161 | 
            +
                it "removes all nil elements and returns self" do
         | 
| 162 | 
            +
                  @array << nil
         | 
| 163 | 
            +
                  assert_same(@array, @array.compact!)
         | 
| 164 | 
            +
                  assert_equal(4, @array.size)
         | 
| 165 | 
            +
                end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                it "returns nil if no elements were removed" do
         | 
| 168 | 
            +
                  assert_nil(@array.compact!)
         | 
| 169 | 
            +
                end
         | 
| 137 170 | 
             
              end
         | 
| 138 171 |  | 
| 139 172 | 
             
              describe "index" do
         | 
    
        data/test/hexapdf/test_stream.rb
    CHANGED
    
    | @@ -1,7 +1,6 @@ | |
| 1 1 | 
             
            # -*- encoding: utf-8 -*-
         | 
| 2 2 |  | 
| 3 3 | 
             
            require 'test_helper'
         | 
| 4 | 
            -
            require 'ostruct'
         | 
| 5 4 | 
             
            require 'stringio'
         | 
| 6 5 | 
             
            require 'tempfile'
         | 
| 7 6 | 
             
            require 'hexapdf/configuration'
         | 
| @@ -80,7 +79,7 @@ end | |
| 80 79 |  | 
| 81 80 | 
             
            describe HexaPDF::Stream do
         | 
| 82 81 | 
             
              before do
         | 
| 83 | 
            -
                @document =  | 
| 82 | 
            +
                @document = Struct.new(:config).new
         | 
| 84 83 | 
             
                @document.config = HexaPDF::Configuration.with_defaults
         | 
| 85 84 | 
             
                @document.instance_variable_set(:@version, '1.2')
         | 
| 86 85 | 
             
                def (@document).unwrap(obj); obj; end
         | 
| @@ -66,7 +66,7 @@ describe HexaPDF::XRefSection do | |
| 66 66 | 
             
                  @xref_section.add_in_use_entry(1, 0, 0)
         | 
| 67 67 | 
             
                  @xref_section.add_in_use_entry(2, 0, 0)
         | 
| 68 68 | 
             
                  result = @xref_section.each_subsection.map {|s| s.map {|e| [e.oid, e.type] }}
         | 
| 69 | 
            -
                  assert_equal([[[1, :in_use], [2, :in_use],
         | 
| 69 | 
            +
                  assert_equal([[[0, :free], [1, :in_use], [2, :in_use],
         | 
| 70 70 | 
             
                                 [3, :free], [4, :free], [5, :free],
         | 
| 71 71 | 
             
                                 [6, :in_use], [7, :in_use],
         | 
| 72 72 | 
             
                                 [8, :free],
         | 
| @@ -373,12 +373,87 @@ describe HexaPDF::Type::AcroForm::AppearanceGenerator do | |
| 373 373 | 
             
                describe "push buttons" do
         | 
| 374 374 | 
             
                  before do
         | 
| 375 375 | 
             
                    @field.initialize_as_push_button
         | 
| 376 | 
            -
                    @widget = @field.create_widget(@page, Rect: [0, 0,  | 
| 376 | 
            +
                    @widget = @field.create_widget(@page, Rect: [0, 0, 100, 50])
         | 
| 377 | 
            +
                    @widget.marker_style(style: 'Test')
         | 
| 377 378 | 
             
                    @generator = HexaPDF::Type::AcroForm::AppearanceGenerator.new(@widget)
         | 
| 378 379 | 
             
                  end
         | 
| 379 380 |  | 
| 380 | 
            -
                  it " | 
| 381 | 
            -
                     | 
| 381 | 
            +
                  it "set the print flag on the widgets" do
         | 
| 382 | 
            +
                    @generator.create_appearances
         | 
| 383 | 
            +
                    assert(@widget.flagged?(:print))
         | 
| 384 | 
            +
                  end
         | 
| 385 | 
            +
             | 
| 386 | 
            +
                  it "removes the hidden flag on the widgets" do
         | 
| 387 | 
            +
                    @widget.flag(:hidden)
         | 
| 388 | 
            +
                    @generator.create_appearances
         | 
| 389 | 
            +
                    refute(@widget.flagged?(:hidden))
         | 
| 390 | 
            +
                  end
         | 
| 391 | 
            +
             | 
| 392 | 
            +
                  it "adds an appropriate form XObject" do
         | 
| 393 | 
            +
                    @generator.create_appearances
         | 
| 394 | 
            +
                    form = @widget[:AP][:N]
         | 
| 395 | 
            +
                    assert_equal(:XObject, form.type)
         | 
| 396 | 
            +
                    assert_equal(:Form, form[:Subtype])
         | 
| 397 | 
            +
                    assert_equal([0, 0, 100, 50], form[:BBox])
         | 
| 398 | 
            +
                    assert_equal(@doc.acro_form.default_resources[:Font][:F1], form[:Resources][:Font][:F1])
         | 
| 399 | 
            +
                  end
         | 
| 400 | 
            +
             | 
| 401 | 
            +
                  it "re-uses the existing form XObject" do
         | 
| 402 | 
            +
                    @generator.create_appearances
         | 
| 403 | 
            +
                    form = @widget[:AP][:N]
         | 
| 404 | 
            +
                    form[:key] = :value
         | 
| 405 | 
            +
                    form.delete(:Subtype)
         | 
| 406 | 
            +
                    @widget[:AP][:N] = @doc.wrap(form, type: HexaPDF::Dictionary)
         | 
| 407 | 
            +
             | 
| 408 | 
            +
                    @generator.create_appearances
         | 
| 409 | 
            +
                    assert_equal(form, @widget[:AP][:N])
         | 
| 410 | 
            +
                    refute(form.key?(:key))
         | 
| 411 | 
            +
                  end
         | 
| 412 | 
            +
             | 
| 413 | 
            +
                  describe "takes the rotation into account" do
         | 
| 414 | 
            +
                    def check_rotation(angle, width, height, matrix)
         | 
| 415 | 
            +
                      @widget[:MK][:R] = angle
         | 
| 416 | 
            +
                      @generator.create_appearances
         | 
| 417 | 
            +
                      form = @widget[:AP][:N]
         | 
| 418 | 
            +
                      assert_equal([0, 0, width, height], form[:BBox].value)
         | 
| 419 | 
            +
                      assert_equal(matrix, form[:Matrix].value)
         | 
| 420 | 
            +
                    end
         | 
| 421 | 
            +
             | 
| 422 | 
            +
                    it "works for 0 degrees" do
         | 
| 423 | 
            +
                      check_rotation(-360, @widget[:Rect].width, @widget[:Rect].height, [1, 0, 0, 1, 0, 0])
         | 
| 424 | 
            +
                    end
         | 
| 425 | 
            +
             | 
| 426 | 
            +
                    it "works for 90 degrees" do
         | 
| 427 | 
            +
                      check_rotation(450, @widget[:Rect].height, @widget[:Rect].width, [0, 1, -1, 0, 0, 0])
         | 
| 428 | 
            +
                    end
         | 
| 429 | 
            +
             | 
| 430 | 
            +
                    it "works for 180 degrees" do
         | 
| 431 | 
            +
                      check_rotation(180, @widget[:Rect].width, @widget[:Rect].height, [0, -1, -1, 0, 0, 0])
         | 
| 432 | 
            +
                    end
         | 
| 433 | 
            +
             | 
| 434 | 
            +
                    it "works for 270 degrees" do
         | 
| 435 | 
            +
                      check_rotation(-90, @widget[:Rect].height, @widget[:Rect].width, [0, -1, 1, 0, 0, 0])
         | 
| 436 | 
            +
                    end
         | 
| 437 | 
            +
                  end
         | 
| 438 | 
            +
             | 
| 439 | 
            +
                  it "adds the button title in the center" do
         | 
| 440 | 
            +
                    @generator.create_appearances
         | 
| 441 | 
            +
                    assert_operators(@widget[:AP][:N].stream,
         | 
| 442 | 
            +
                                     [[:save_graphics_state],
         | 
| 443 | 
            +
                                      [:set_device_gray_non_stroking_color, [0.5]],
         | 
| 444 | 
            +
                                      [:append_rectangle, [0, 0, 100, 50]],
         | 
| 445 | 
            +
                                      [:fill_path_non_zero],
         | 
| 446 | 
            +
                                      [:append_rectangle, [0.5, 0.5, 99.0, 49.0]],
         | 
| 447 | 
            +
                                      [:stroke_path],
         | 
| 448 | 
            +
                                      [:restore_graphics_state],
         | 
| 449 | 
            +
                                      [:save_graphics_state],
         | 
| 450 | 
            +
                                      [:set_font_and_size, [:F1, 9]],
         | 
| 451 | 
            +
                                      [:begin_text],
         | 
| 452 | 
            +
                                      [:move_text, [41.2475, 22.7005]],
         | 
| 453 | 
            +
                                      [:show_text, ["Test"]],
         | 
| 454 | 
            +
                                      [:end_text],
         | 
| 455 | 
            +
                                      [:restore_graphics_state]],
         | 
| 456 | 
            +
                                     )
         | 
| 382 457 | 
             
                  end
         | 
| 383 458 | 
             
                end
         | 
| 384 459 | 
             
              end
         | 
| @@ -236,6 +236,13 @@ describe HexaPDF::Type::AcroForm::ButtonField do | |
| 236 236 | 
             
                  assert(widget[:AP][:N][:test])
         | 
| 237 237 | 
             
                end
         | 
| 238 238 |  | 
| 239 | 
            +
                it "works for push buttons" do
         | 
| 240 | 
            +
                  @field.initialize_as_push_button
         | 
| 241 | 
            +
                  @field.create_widget(@doc.pages.add, Rect: [0, 0, 100, 50])
         | 
| 242 | 
            +
                  @field.create_appearances
         | 
| 243 | 
            +
                  assert(@field[:AP][:N])
         | 
| 244 | 
            +
                end
         | 
| 245 | 
            +
             | 
| 239 246 | 
             
                it "won't generate appearances if they already exist" do
         | 
| 240 247 | 
             
                  widget = @field.create_widget(@doc.pages.add, Rect: [0, 0, 0, 0])
         | 
| 241 248 | 
             
                  @field.create_appearances
         | 
| @@ -262,12 +269,6 @@ describe HexaPDF::Type::AcroForm::ButtonField do | |
| 262 269 | 
             
                  refute_same(yes, widget.appearance_dict.normal_appearance[:Yes])
         | 
| 263 270 | 
             
                end
         | 
| 264 271 |  | 
| 265 | 
            -
                it "fails for push buttons as they are not implemented yet" do
         | 
| 266 | 
            -
                  @field.flag(:push_button)
         | 
| 267 | 
            -
                  @field.create_widget(@doc.pages.add, Rect: [0, 0, 0, 0])
         | 
| 268 | 
            -
                  assert_raises(HexaPDF::Error) { @field.create_appearances }
         | 
| 269 | 
            -
                end
         | 
| 270 | 
            -
             | 
| 271 272 | 
             
                it "uses the configuration option acro_form.appearance_generator" do
         | 
| 272 273 | 
             
                  @doc.config['acro_form.appearance_generator'] = 'NonExistent'
         | 
| 273 274 | 
             
                  assert_raises(Exception) { @field.create_appearances }
         | 
| @@ -193,9 +193,14 @@ describe HexaPDF::Type::AcroForm::Field do | |
| 193 193 |  | 
| 194 194 | 
             
                it "extracts an embedded widget into a standalone object if necessary" do
         | 
| 195 195 | 
             
                  widget1 = @field.create_widget(@page, Rect: [1, 2, 3, 4])
         | 
| 196 | 
            +
                  # Make sure that the field/widget looks like as if it has been loaded from a file
         | 
| 197 | 
            +
                  @doc.revisions.current.update(widget1)
         | 
| 198 | 
            +
                  assert_equal(@field, widget1)
         | 
| 199 | 
            +
             | 
| 196 200 | 
             
                  widget2 = @field.create_widget(@doc.pages.add, Rect: [2, 1, 4, 3])
         | 
| 197 201 | 
             
                  kids = @field[:Kids]
         | 
| 198 202 |  | 
| 203 | 
            +
                  assert_kind_of(HexaPDF::Type::AcroForm::Field, @doc.object(@field.oid))
         | 
| 199 204 | 
             
                  assert_equal(2, kids.length)
         | 
| 200 205 | 
             
                  refute_same(widget1, kids[0])
         | 
| 201 206 | 
             
                  assert_same(widget2, kids[1])
         | 
| @@ -558,13 +558,23 @@ describe HexaPDF::Type::AcroForm::Form do | |
| 558 558 | 
             
                    assert_equal(:Tx4, @acro_form[:Fields][2][:Kids][0][:T])
         | 
| 559 559 | 
             
                    assert_equal(@acro_form[:Fields][2], @acro_form[:Fields][2][:Kids][0][:Parent])
         | 
| 560 560 | 
             
                  end
         | 
| 561 | 
            +
             | 
| 562 | 
            +
                  it "ensures that objects loaded as widget are stored as field" do
         | 
| 563 | 
            +
                    @acro_form[:Fields][2] = @doc.add({T: :WidgetField, Type: :Annot, Subtype: :Widget})
         | 
| 564 | 
            +
                    assert_kind_of(HexaPDF::Type::Annotations::Widget, @acro_form[:Fields][2])
         | 
| 565 | 
            +
             | 
| 566 | 
            +
                    assert(@acro_form.validate)
         | 
| 567 | 
            +
                    field = @acro_form[:Fields][0]
         | 
| 568 | 
            +
                    assert_kind_of(HexaPDF::Type::AcroForm::Field, field)
         | 
| 569 | 
            +
                    assert_equal(:WidgetField, field.full_field_name)
         | 
| 570 | 
            +
                  end
         | 
| 561 571 | 
             
                end
         | 
| 562 572 |  | 
| 563 573 | 
             
                describe "combining fields with the same name" do
         | 
| 564 574 | 
             
                  before do
         | 
| 565 575 | 
             
                    @acro_form[:Fields] = [
         | 
| 566 576 | 
             
                      @doc.add({T: 'e', Subtype: :Widget, Rect: [0, 0, 0, 1]}),
         | 
| 567 | 
            -
                      @doc.add({T: 'e', Subtype: :Widget, Rect: [0, 0, 0, 2]}),
         | 
| 577 | 
            +
                      @merged_field = @doc.add({T: 'e', Subtype: :Widget, Rect: [0, 0, 0, 2]}),
         | 
| 568 578 | 
             
                      @doc.add({T: 'Tx2'}),
         | 
| 569 579 | 
             
                      @doc.add({T: 'e', Kids: [{Subtype: :Widget, Rect: [0, 0, 0, 3]}]}),
         | 
| 570 580 | 
             
                    ]
         | 
| @@ -576,6 +586,12 @@ describe HexaPDF::Type::AcroForm::Form do | |
| 576 586 | 
             
                    assert_equal([[0, 0, 0, 1], [0, 0, 0, 2], [0, 0, 0, 3]],
         | 
| 577 587 | 
             
                                 @acro_form.field_by_name('e').each_widget.map {|w| w[:Rect] })
         | 
| 578 588 | 
             
                  end
         | 
| 589 | 
            +
             | 
| 590 | 
            +
                  it "deletes the combined and now unneeded field objects" do
         | 
| 591 | 
            +
                    assert(@acro_form.validate)
         | 
| 592 | 
            +
                    assert(@merged_field.null?)
         | 
| 593 | 
            +
                    assert(@doc.object(@merged_field.oid).null?)
         | 
| 594 | 
            +
                  end
         | 
| 579 595 | 
             
                end
         | 
| 580 596 |  | 
| 581 597 | 
             
                describe "automatically creates the terminal fields; appearances" do
         | 
| @@ -82,6 +82,20 @@ describe HexaPDF::Type::AcroForm::JavaScriptActions do | |
| 82 82 | 
             
                    assert_equal('1.234,57', value)
         | 
| 83 83 | 
             
                  end
         | 
| 84 84 |  | 
| 85 | 
            +
                  it "works with the special Infinity and NaN values" do
         | 
| 86 | 
            +
                    @value = 'Infinity'
         | 
| 87 | 
            +
                    assert_format('2, 2, 0, 0, "", false', "Inf", "black")
         | 
| 88 | 
            +
                    @value = '-Infinity'
         | 
| 89 | 
            +
                    assert_format('2, 2, 0, 0, "", false', "-Inf", "black")
         | 
| 90 | 
            +
                    @value = 'Nan'
         | 
| 91 | 
            +
                    assert_format('2, 2, 0, 0, "", false', "NaN", "black")
         | 
| 92 | 
            +
                  end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                  it "works if the value is nil" do
         | 
| 95 | 
            +
                    @value = nil
         | 
| 96 | 
            +
                    assert_format('2, 2, 0, 0, "", false', "0,00", "black")
         | 
| 97 | 
            +
                  end
         | 
| 98 | 
            +
             | 
| 85 99 | 
             
                  it "does nothing to the value if the JavaScript method could not be determined " do
         | 
| 86 100 | 
             
                    assert_format('2, 3, 0, 0, " E", false, a', "1234567.898765", nil)
         | 
| 87 101 | 
             
                  end
         | 
| @@ -244,6 +258,13 @@ describe HexaPDF::Type::AcroForm::JavaScriptActions do | |
| 244 258 | 
             
                    assert_calculation('SUM', [@field1, @field2], "30.54")
         | 
| 245 259 | 
             
                  end
         | 
| 246 260 |  | 
| 261 | 
            +
                  it "works with the special values Infinity and NaN" do
         | 
| 262 | 
            +
                    @field1.field_value = "Infinity"
         | 
| 263 | 
            +
                    assert_calculation('SUM', [@field1, @field2], "Infinity")
         | 
| 264 | 
            +
                    @field1.field_value = "NaN"
         | 
| 265 | 
            +
                    assert_calculation('SUM', [@field1, @field2], "NaN")
         | 
| 266 | 
            +
                  end
         | 
| 267 | 
            +
             | 
| 247 268 | 
             
                  it "returns nil if a field cannot be resolved" do
         | 
| 248 269 | 
             
                    @action[:JS] = 'AFSimple_Calculate("SUM", ["unknown"]);'
         | 
| 249 270 | 
             
                    assert_nil(@klass.calculate(@form, @action))
         | 
| @@ -130,9 +130,12 @@ describe HexaPDF::Type::AcroForm::TextField do | |
| 130 130 | 
             
                  assert_raises(HexaPDF::Error) { @field.field_value = 'test' }
         | 
| 131 131 | 
             
                end
         | 
| 132 132 |  | 
| 133 | 
            -
                it " | 
| 133 | 
            +
                it "calls acro_form.text_field.on_max_len_exceeded  if the value exceeds the length set by /MaxLen" do
         | 
| 134 134 | 
             
                  @field[:MaxLen] = 5
         | 
| 135 135 | 
             
                  assert_raises(HexaPDF::Error) { @field.field_value = 'testdf' }
         | 
| 136 | 
            +
                  @doc.config['acro_form.text_field.on_max_len_exceeded'] = proc {|f, v| v }
         | 
| 137 | 
            +
                  @field.field_value = 'testdf'
         | 
| 138 | 
            +
                  assert_equal('testdf', @field[:V])
         | 
| 136 139 | 
             
                end
         | 
| 137 140 | 
             
              end
         | 
| 138 141 |  | 
| @@ -278,6 +281,9 @@ describe HexaPDF::Type::AcroForm::TextField do | |
| 278 281 | 
             
                  assert(@field.validate)
         | 
| 279 282 | 
             
                  @field[:MaxLen] = 2
         | 
| 280 283 | 
             
                  refute(@field.validate)
         | 
| 284 | 
            +
                  @doc.config['acro_form.text_field.on_max_len_exceeded'] = proc {|field, str| "Hello" }
         | 
| 285 | 
            +
                  assert(@field.validate)
         | 
| 286 | 
            +
                  assert_equal('Hello', @field[:V])
         | 
| 281 287 | 
             
                  @field[:V] = nil
         | 
| 282 288 | 
             
                  assert(@field.validate)
         | 
| 283 289 | 
             
                end
         |