require 'spec_helper' require 'set' require 'pathname' describe Prawn::Images do let(:pdf) { create_pdf } let(:filename) { "#{Prawn::DATADIR}/images/pigs.jpg" } it "onlies embed an image once, even if it's added multiple times" do pdf.image filename, at: [100, 100] pdf.image filename, at: [300, 300] output = pdf.render images = PDF::Inspector::XObject.analyze(output) # there should be 2 images in the page resources expect(images.page_xobjects.first.size).to eq(2) # but only 1 image xobject expect(output.scan(%r{/Type /XObject}).size).to eq(1) end it 'returns the image info object' do info = pdf.image(filename) expect(info).to be_a_kind_of(Prawn::Images::JPG) expect(info.height).to eq(453) end it 'accepts IO objects' do file = File.open(filename, 'rb') info = pdf.image(file) expect(info.height).to eq(453) end it 'rewinds IO objects to be able to embed them multiply' do file = File.open(filename, 'rb') pdf.image(file) info = pdf.image(file) expect(info.height).to eq(453) end it 'accepts Pathname objects' do info = pdf.image(Pathname.new(filename)) expect(info.height).to eq(453) end context 'setting the length of the bytestream' do it 'correctlies work with images from Pathname objects' do pdf.image(Pathname.new(filename)) expect(pdf).to have_parseable_xobjects end it 'correctlies work with images from IO objects' do pdf.image(File.open(filename, 'rb')) expect(pdf).to have_parseable_xobjects end it 'correctlies work with images from IO objects not set to mode rb' do pdf.image(File.open(filename, 'r')) expect(pdf).to have_parseable_xobjects end end it 'raise_errors an UnsupportedImageType if passed a BMP' do filename = "#{Prawn::DATADIR}/images/tru256.bmp" expect { pdf.image filename, at: [100, 100] } .to raise_error(Prawn::Errors::UnsupportedImageType) end it 'raise_errors an UnsupportedImageType if passed an interlaced PNG' do filename = "#{Prawn::DATADIR}/images/dice_interlaced.png" expect { pdf.image filename, at: [100, 100] } .to raise_error(Prawn::Errors::UnsupportedImageType) end it 'bumps PDF version to 1.5 or greater on embedding 16-bit PNGs' do pdf.image "#{Prawn::DATADIR}/images/16bit.png" expect(pdf.state.version).to be >= 1.5 end it 'embeds 16-bit alpha channels for 16-bit PNGs' do pdf.image "#{Prawn::DATADIR}/images/16bit.png" output = pdf.render expect(output).to match(%r{/BitsPerComponent 16}) expect(output).to_not match(%r{/BitsPerComponent 8}) end it 'flows an image to a new page if it will not fit on a page' do pdf.image filename, fit: [600, 600] pdf.image filename, fit: [600, 600] output = StringIO.new(pdf.render, 'r+') hash = PDF::Reader::ObjectHash.new(output) pages = hash.values.find do |obj| obj.is_a?(Hash) && obj[:Type] == :Pages end[:Kids] expect(pages.size).to eq(2) expect(hash[pages[0]][:Resources][:XObject].keys).to eq([:I1]) expect(hash[pages[1]][:Resources][:XObject].keys).to eq([:I2]) end it 'does not flow an image to a new page if it will fit on one page' do pdf.image filename, fit: [400, 400] pdf.image filename, fit: [400, 400] output = StringIO.new(pdf.render, 'r+') hash = PDF::Reader::ObjectHash.new(output) pages = hash.values.find do |obj| obj.is_a?(Hash) && obj[:Type] == :Pages end[:Kids] expect(pages.size).to eq(1) expect(Set.new(hash[pages[0]][:Resources][:XObject].keys)).to eq( Set.new([:I1, :I2]) ) end it 'does not start a new page just for a stretchy bounding box' do allow(pdf).to receive(:start_new_page) pdf.bounding_box([0, pdf.cursor], width: pdf.bounds.width) do pdf.image filename end expect(pdf).to_not have_received(:start_new_page) end describe ':fit option' do it 'fits inside the defined constraints' do info = pdf.image filename, fit: [100, 400] expect(info.scaled_width).to be <= 100 expect(info.scaled_height).to be <= 400 info = pdf.image filename, fit: [400, 100] expect(info.scaled_width).to be <= 400 expect(info.scaled_height).to be <= 100 info = pdf.image filename, fit: [604, 453] expect(info.scaled_width).to eq(604) expect(info.scaled_height).to eq(453) end it 'moves text position' do y = pdf.y pdf.image filename, fit: [100, 400] expect(pdf.y).to be < y end end describe ':at option' do it 'does not move text position' do y = pdf.y pdf.image filename, at: [100, 400] expect(pdf.y).to eq(y) end end describe ':width option without :height option' do it 'scales the width and height' do info = pdf.image filename, width: 225 expect(info.scaled_height).to eq(168.75) expect(info.scaled_width).to eq(225.0) end end describe ':height option without :width option' do it 'scales the width and height' do info = pdf.image filename, height: 225 expect(info.scaled_height).to eq(225.0) expect(info.scaled_width).to eq(300.0) end end end