packages feed

line2pdf (empty) → 0.0.1

raw patch · 5 files changed

+318/−0 lines, 5 filesdep +basedep +bytestringdep +containerssetup-changed

Dependencies added: base, bytestring, containers

Files

+ LICENSE view
@@ -0,0 +1,20 @@+Copyright 2008 by Audrey Tang <audreyt@audreyt.org>++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ README view
@@ -0,0 +1,1 @@+"line2pdf" is a simple command-line utility to convert text into PDF.
+ Setup.lhs view
@@ -0,0 +1,14 @@+#!/usr/bin/env runhaskell+\begin{code}+import System.Cmd+import Distribution.Simple++main = defaultMainWithHooks $ simpleUserHooks+    { buildHook = myBuild (buildHook simpleUserHooks) }++myBuild doBuild x y z w = do+    rv <- doBuild x y z w+    system "make -f Makefile.pdfdump"+    return rv++\end{code}
+ line2pdf.cabal view
@@ -0,0 +1,19 @@+name:               line2pdf+version:            0.0.1+copyright:          2008 Audrey Tang+license:            BSD3+license-file:       LICENSE+author:             Audrey Tang <audreyt@audreyt.org>+maintainer:         Audrey Tang <audreyt@audreyt.org>+synopsis:           Simple command-line utility to convert text into PDF+description:        Simple command-line utility to convert text into PDF+stability:          experimental+build-type:         Simple+category:           Text+extra-source-files: README++executable:         line2pdf+main-is:            line2pdf.hs+extensions:         ImplicitParams+build-depends:      base, bytestring, containers+hs-source-dirs:     .
+ line2pdf.hs view
@@ -0,0 +1,264 @@+{-# LANGUAGE ImplicitParams #-}+module Main where+import Data.IORef+import System.IO+import System.IO.Unsafe+import System.Exit+import System.Environment+import Control.Applicative+import qualified Data.ByteString.Lazy.Char8 as L+import qualified Data.IntMap as IM++{-# NOINLINE __POS__ #-}+__POS__ :: IORef Int+__POS__ = unsafePerformIO (newRef 0)++{-# NOINLINE __OBJ__ #-}+__OBJ__ :: IORef Int+__OBJ__ = unsafePerformIO (newRef 0)++{-# NOINLINE __LOC__ #-}+__LOC__ :: IORef (IM.IntMap String)+__LOC__ = unsafePerformIO (newRef IM.empty)++{-# NOINLINE __PAGE__ #-}+__PAGE__ :: IORef [Obj]+__PAGE__ = unsafePerformIO (newRef [])++type M = IO+type Obj = Int++main = do+    args <- getArgs++    input <- case args of+        []      -> do+            putStrLn "Usage: line2pdf input.txt > output.pdf"+            putStrLn "  (Form feed (^L) in input denotes a pagebreak.)"+            exitWith ExitSuccess+        (i:_)   -> return i++    hSetBinaryMode stdout True++    pr$ "%PDF-1.2\n" ++ "%\xE2\xE3\xCF\xD3\n"++    (info, root, tPages, resources) <- writeHeader++    pageObjs <- let ?tPages = tPages+                    ?resources = resources in writePages =<< (L.lines <$> L.readFile input)++    markLocation root+    writeObj root $ do+        pr$ "/Type/Catalog" ++ "/Pages "+        pr$ show tPages ++ " 0 R" ++    markLocation tPages+    writeObj tPages $ do+        pr$ "/Type/Pages" ++ "/Count "+        pr$ show (length pageObjs)+         ++ "/MediaBox[0 0 "+         ++ show pageWidth ++ " " ++ show pageHeight+        pr$ "]" ++ "/Kids["+        pr$ concatMap ((++ " 0 R ") . show) pageObjs+        pr$ "]"++    xfer <- currentLocation++    objCount <- incrObj+    pr$ "xref\n" ++ "0 " ++ show objCount ++ "\n"+     ++ "0000000000 65535 f \r"++    writeLocations++    pr$ "trailer\n" ++ "<<" ++ "/Size "+    pr$ show objCount++    pr$ "/Root " ++ show root ++ " 0 R"+    pr$ "/Info " ++ show info ++ " 0 R"+    pr$ ">>\n" ++ "startxref\n"+    pr$ show xfer ++ "\n" ++ "%%EOF\n"++writeObj :: Obj -> M a -> M a+writeObj obj f = do+    pr$ show obj ++ " 0 obj" ++ "<<"+    rv <- f+    pr$ ">>" ++ "endobj\n"+    return rv++writeLocations = do+    locs <- IM.elems <$> readRef __LOC__+    pr$ concatMap fmt locs+    where+    fmt x = pad ++ x ++ " 00000 n \r"+        where+        pad = replicate (10-l) '0'+        l = length x ++writeHeader = do+    info <- markObj $ \info -> do+        pr$ "/CreationDate(D:20080707163949+08'00')"+         ++ "/Producer(line2pdf.hs)"+         ++ "/Title(Untitled)"+        return info+    encoding <- markObj $ \encoding -> do+        pr$ strDefaultEncoding+        return encoding+    everyFont <- (`mapM` ([1..] `zip` baseFonts)) $ \(n, font) -> do+        markObj $ \obj -> do+            pr$ "/Type/Font" ++ "/Subtype/Type1" ++ "/Name/F"+            pr$ show n+            pr$ "/Encoding " ++ show encoding ++ " 0 R"+            pr$ font+            return $ "/F" ++ show n ++ " " ++ show obj ++ " 0 R"+    root    <- incrObj+    tPages  <- incrObj+    markObj $ \resources -> do+        pr$ "/Font<<" ++ concat everyFont ++ ">>"+            ++ "/ProcSet[/PDF/Text]" ++ "/XObject<<>>"+        return (info, root, tPages, resources)++baseFonts =+    [ "/BaseFont/Courier"+    , "/BaseFont/Courier-Oblique"+    , "/BaseFont/Courier-Bold"+    , "/BaseFont/Courier-BoldOblique"+    , "/BaseFont/Helvetica"+    , "/BaseFont/Helvetica-Oblique"+    , "/BaseFont/Helvetica-Bold"+    , "/BaseFont/Helvetica-BoldOblique"+    , "/BaseFont/Times-Roman"+    , "/BaseFont/Times-Italic"+    , "/BaseFont/Times-Bold"+    , "/BaseFont/Times-BoldItalic"+    , "/BaseFont/Symbol"+    , "/BaseFont/ZapfDingbats"+    ]+    +pr :: String -> M ()+pr str = do+    putStr str+    modifyRef __POS__ (+ (length str))++currentLocation = readRef __POS__++newRef = newIORef+readRef = readIORef+writeRef = writeIORef+modifyRef = modifyIORef++incrObj :: M Obj+incrObj = do+    obj <- succ <$> readRef __OBJ__+    writeRef __OBJ__ obj+    return obj++markObj :: (Obj -> M a) -> M a+markObj f = do+    obj <- incrObj+    markLocation obj+    writeObj obj (f obj)++markLocation :: Obj -> M ()+markLocation obj = do+    loc <- currentLocation+    modifyRef __LOC__ $ IM.insert obj (show loc)++startPage :: (?tPages :: Obj, ?resources :: Obj) => M Int+startPage = do+    markObj $ \obj -> do+        modifyRef __PAGE__ (obj:)+        pr$ "/Type/Page"+        pr$ "/Parent " ++ show ?tPages ++ " 0 R"+        pr$ "/Resources " ++ show ?resources ++ " 0 R"+        pr$ "/Contents " ++ show (succ obj) ++ " 0 R"+        pr$ "/Rotate 0"++    obj <- incrObj+    markLocation obj+    pr$ show obj ++ " 0 obj" ++ "<<"+    pr$ "/Length " ++ show (succ obj) ++ " 0 R"+    pr$ ">>" ++ "stream\n"++    streamPos <- currentLocation+    pr$ "BT\n";+    let fontN = 1+        ptSize = 12+    pr$ "/F" ++ show fontN ++ " " ++ show ptSize ++ " Tf\n"+    pr$ "1 0 0 1 50 " ++ show (pageHeight - 40) ++ " Tm\n"+    pr$ "12 TL\n"++    return streamPos++endPage streamStart = do+    pr$ "ET\n"+    streamEnd <- currentLocation+    pr$ "endstream\n"+     ++ "endobj\n"++    obj <- incrObj+    markLocation obj++    pr$ show obj ++ " 0 obj\n"+     ++ show (streamEnd - streamStart) ++ "\n"+     ++ "endobj\n"++writePages :: (?tPages :: Obj, ?resources :: Obj) => [L.ByteString] -> M [Obj]+writePages lns = do+    pos <- newRef =<< startPage++    (`mapM_` lns) $ \ln -> do+        case fromEnum (L.length ln) of+            1 | L.head ln == '\f' -> do+                endPage =<< readRef pos+                writeRef pos =<< startPage+            len -> do+                pr$ "T*("+                L.putStr ln+                modifyRef __POS__ (+ len)+                pr$ ")Tj\n"++    endPage =<< readRef pos+    reverse <$> readRef __PAGE__++strDefaultEncoding = "/Type/Encoding"+    ++ "/Differences[0 /.notdef/.notdef/.notdef/.notdef"+    ++ "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef"+    ++ "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef"+    ++ "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef"+    ++ "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef"+    ++ "/.notdef/.notdef/.notdef/.notdef/space/exclam"+    ++ "/quotedbl/numbersign/dollar/percent/ampersand"+    ++ "/quoteright/parenleft/parenright/asterisk/plus/comma"+    ++ "/hyphen/period/slash/zero/one/two/three/four/five"+    ++ "/six/seven/eight/nine/colon/semicolon/less/equal"+    ++ "/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L"+    ++ "/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft"+    ++ "/backslash/bracketright/asciicircum/underscore"+    ++ "/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p"+    ++ "/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright"+    ++ "/asciitilde/.notdef/.notdef/.notdef/.notdef/.notdef"+    ++ "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef"+    ++ "/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef"+    ++ "/dotlessi/grave/acute/circumflex/tilde/macron/breve"+    ++ "/dotaccent/dieresis/.notdef/ring/cedilla/.notdef"+    ++ "/hungarumlaut/ogonek/caron/space/exclamdown/cent"+    ++ "/sterling/currency/yen/brokenbar/section/dieresis"+    ++ "/copyright/ordfeminine/guillemotleft/logicalnot/hyphen"+    ++ "/registered/macron/degree/plusminus/twosuperior"+    ++ "/threesuperior/acute/mu/paragraph/periodcentered"+    ++ "/cedilla/onesuperior/ordmasculine/guillemotright"+    ++ "/onequarter/onehalf/threequarters/questiondown/Agrave"+    ++ "/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE"+    ++ "/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave"+    ++ "/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve"+    ++ "/Oacute/Ocircumflex/Otilde/Odieresis/multiply/Oslash"+    ++ "/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn"+    ++ "/germandbls/agrave/aacute/acircumflex/atilde/adieresis"+    ++ "/aring/ae/ccedilla/egrave/eacute/ecircumflex"+    ++ "/edieresis/igrave/iacute/icircumflex/idieresis/eth"+    ++ "/ntilde/ograve/oacute/ocircumflex/otilde/odieresis"+    ++ "/divide/oslash/ugrave/uacute/ucircumflex/udieresis"+    ++ "/yacute/thorn/ydieresis]"++pageWidth = 792+pageHeight = 612