dPDF = {} -- object 1 :: catalog -- object 2 :: outlines -- object 3 :: pages -- TODO: addPage adds a header and reserves an object space -- don't necessarily keep space for a font on each page function dPDF.init() dPDF.buffer = "" dPDF.pages = 1 dPDF.outlines = 1 dPDF.fonts = 1 dPDF.objects = 4 dPDF.object = {} dPDF.page = {} dPDF.page_content = {} dPDF.font_content = {} end function dPDF.emit( s ) dPDF.buffer = dPDF.buffer .. s .. "\n" end function dPDF.makeStream( s ) return "\t<< /Length " .. s:len()+17 .. ">>\nstream\n" .. s .. "\nendstream" end function dPDF.addPage() print( "wrote page " .. dPDF.pages ) dPDF.page[dPDF.pages] = "<<\t" .. "/Type /Page\n" .. "\t/Parent 3 0 R\n" .. "\t/MediaBox [ 0 0 612 792 ]\n" .. "\t/Contents " .. 6 + (dPDF.pages-1)*3 .. " 0 R\n" .. "\t/Resources << /ProcSet [/PDF] /Font << /F1 " .. 5+(dPDF.pages-1)*3 .. " 0 R >> >>\n" .. ">>" dPDF.font_content[dPDF.fonts] = "<<\t" .. "/Type /Font\n" .. "\t/Subtype /Type1\n" .. "\t/Name /F" .. dPDF.fonts .. "\n" .. "\t/BaseFont /Times-Roman\n" .. --"\t/Encoding /PDFDocEncoding\n" .. "\t/Encoding <>" .. ">> " dPDF.pages = dPDF.pages + 1 dPDF.fonts = dPDF.fonts + 1 dPDF.objects = dPDF.objects + 2 end function dPDF.addPageContent( i, s ) dPDF.page_content[i] = dPDF.makeStream( "BT /F1 14 Tf 100 692 Td (" .. s .. ") Tj ET" ) end function dPDF.addPageContentHex( i, s ) dPDF.page_content[i] = dPDF.makeStream( "BT /F1 14 Tf 100 692 Td <" .. s .. "> Tj ET" ) end function dPDF.makeObject( i, s ) return i .. " 0 obj\n" .. s .. "\nendobj\n" end function dPDF.writeContent() _offset = {} -- write header dPDF.emit( "%PDF-1.4" ) -- write catalog _offset[1] = dPDF.buffer:len() dPDF.emit( dPDF.makeObject( 1, "<<\t/Type /Catalog\n\t/Outlines 2 0 R\n\t/Pages 3 0 R\n>>" ) ) -- write outlines _offset[2] = dPDF.buffer:len() dPDF.emit( dPDF.makeObject( 2, "<<\t/Type /Outlines\n\t/Count 0\n>>" ) ) -- write page master local _pages = "" for i = 1, dPDF.pages-1 do _pages = _pages .. 4 + 3 * (i-1) .. " 0 R " end _offset[3] = dPDF.buffer:len() dPDF.emit( dPDF.makeObject( 3, "<<\t/Type /Pages\n\t/Kids [ " .. _pages .. " ]\n\t/Count " .. dPDF.pages-1 .. "\n>>" ) ) -- write page, page content and font data for i = 1, dPDF.pages-1 do _offset[4+(i-1)*3] = dPDF.buffer:len() dPDF.emit( dPDF.makeObject( 4 + (i-1) * 3, dPDF.page[i] ) ) _offset[5+(i-1)*3] = dPDF.buffer:len() dPDF.emit( dPDF.makeObject( 5 + (i-1) * 3, dPDF.font_content[i] ) ) _offset[6+(i-1)*3] = dPDF.buffer:len() dPDF.emit( dPDF.makeObject( 6 + (i-1) * 3, dPDF.page_content[i] ) ) end end function dPDF.writeXref() dPDF.emit( "xref" ) dPDF.emit( "0 " .. dPDF.objects + 1 ) dPDF.emit( "0000000000 65535 f" ) for i = 1, #_offset do dPDF.emit( string.format( "%010i 00000 f ", _offset[i] or "666" ) ) end end function dPDF.writePDF() dPDF.writeContent() dPDF.writeXref() dPDF.emit( "trailer << /Size " .. 6+(dPDF.pages-1)*3 .. " /Root 1 0 R >>" ) dPDF.emit( "startxref\n0+" ) dPDF.emit( "%%EOF" ) end function dPDF.outputPDF( s ) local f = io.open( s, "w" ) f:write( dPDF.buffer ) f:close() end ---------------- TEST function test() dPDF.init() dPDF.addPage() dPDF.addPage() dPDF.addPageContentHex( 1, "02" ) dPDF.addPageContent( 2, "salut, lume!" ) dPDF.writePDF() dPDF.outputPDF( "lpdf.pdf" ) end test()