Biblioteca HPDF

De Wikihaskell
Saltar a: navegación, buscar
Biblioteca HPDF
Generación de documentos pdf
Lenguaje Haskell
Biblioteca HPDF
Autores Luis Nadal Mora
Diego Garcia Arriaza
Isabel Mansilla Rodríguez

HPDF es una biblioteca encargada de la generación de documentos pdf; apoyo de varias páginas, transiciones, esquemas, anotaciones, compresión, colores, formas, diseños, imágenes JPEG, fuentes, composición

La biblioteca se puede descargar de la URL [1], así como la descripción de todos los módulos que incorpora.


Contenido

Instalación

Se recomienda para su instalación visitar el siguiente artículo: Biblioteca de empaquetamiento Cabal

Instalación en Linux (Ubuntu)

Antes de instalar nada sobre nuestra biblioteca debemos de instalar tanto cabal como el interprete de cabal dado que la bilbioteca se encuentra empaquetada con este. Para ello procedemos a su instalación. Haré una breve descripción del proceso de instalación ya que toda la información se encuentra en el enlace superior.

Instalando Cabal

1- Instalamos las dependencias que seguramente necesitaremos:

     sudo apt-get install ghc6 libghc6-parsec-dev libghc6-network-dev libghc6-http-dev libghc6-mtl-dev zlib1g-dev

2- Descargamos el intérprete de [2], lo descomprimimos, y desde dentro de la carpeta ejecutamos

     ./bootstrap.sh

3- Una vez hecho esto, añadimos la ruta de cabal al $PATH. Hacemos lo siguiente desde la consola:

     sudo ~/.bashrc ~/.bashrc-backup
     sudo gedit ~/.bashrc&
     Añadimos al final del fichero:
        PATH=$PATH:~/.cabal/bin
        export PATH
     Guardamos el documento y cerramos el fichero.
     Reiniciamos la sesión
     Escribimos echo $PATH y comprobamos que aparezca ~/.cabal/bin

4- Si todo ha ido bien, solo tenemos que actualizar

     cabal update

5- A continuación instalamos el paquete Cabal, para ello descargamos [3], descomprimimos el fichero y desde dentro ejecutamos las siguientes ordenes:

  a- Si no somos administradores:
     ghc --make Setup
     ./Setup configure --user
     ./Setup build
     ./Setup install
  b- Si somos administradores
     ghc --make Setup
     ./Setup configure
     ./Setup build
     sudo ./Setup install

Instalando Biblioteca HPDF

1- Descargamos la bilbioteca de [4].

2- La descomprimimos y nos situamos dentro de la carpeta generada:

     tar xzf HPDF-1.4.2.tar.gz
     cd HPDF-1.4.2

Y ejecutamos la orden:

     runhaskell Setup configure

3- Si es la primera vez que instalamos uns biblioteca en cabal o simplemente no tenemos las dependencias necesarias nos mostrará un mensaje como el siguiente:

     Al least the following dependences are missing:
     binary >= 0.4, zlib >= 0.5
  • - Estas bibliotecas se encuentran tambien en la página de hackage y su instalación es identica a la de la principal, no obstante procederé a describirlas detalladamente.

4- Instalación de Binary:

Vamos a descargarnos el paquete correspondiente a [5], lo descomprimimos y nos desplazamos a la carpeta que crea:

     tar xzf binary-0.5.0.2.tar.gz
     cd binary-0.5.0.2

Una vez dentro ejecutamos las siguientes ordenes:

     runhaskell Setup configure
     runhaskell Setup build
     sudo runhaskell Setup install

5- Instalación de Zlib: (Es exactamente igual que para Binary)

Vamos a descargarnos el paquete correspondiente a [6], lo descomprimimos y nos desplazamos a la carpeta que crea:

     tar xzf zlib-0.5.2.0.tar.gz
     cd zlib-0.5.2.0

Una vez dentro ejecutamos las siguientes ordenes:

     runhaskell Setup configure
     runhaskell Setup build
     sudo runhaskell Setup install

6- Ya tenemos todas las dependencias necesarias para instalar HPDF, por tanto nos desplazamos de nuevo a la carpeta que contiene la biblioteca (HPDF-1.4.2), y de nuevo escribimos las mismas ordenes anteriores:

     runhaskell Setup configure
     runhaskell Setup build
     sudo runhaskell Setup install

Instalación en Windows (XP)

En esta sección vamos a instalar la biblioteca HPDF en Windows XP, pero antes vamos a descargar e instalar los paquetes necesarios para la instalación y ejecución de nuestra biblioteca.

Instalando GHC

Primero vamos a instalar el compilador GHC que será necesario para el resto de la instalación, se puede descargar en el siguiente enlace [7]. Después de la descarga instalamos GHC siguiendo las instrucciones.

Instalando Cabal

Descargamos el paquete del siguiente enlace [8], luego copiamos el fichero en el path del sistepa para poder llamarlo desde la línea de comando.
Para comprobarlo podemos ejecutar la siguiente orden desde la carpeta donde se encuentre el fichero.
Por ejemplo si la hemos copiado en el Escritorio debemos ejecutar la siguiente orden:

     C:\Documents and Settings\Administrador\Escritorio>cabal --version
     cabal-install version 0.6.2
     using version 1.6.0.2 of the Cabal library

Luego comprobamos que existe la siguiente carpeta y si no existe la creamos nosotros, debemos comprobar que tenga los permisos adecuados.

     C:\program files\haskell.

La primera vez que utilizamos cabal debemos ejecutar la siguiente orden:

     >cabal update
      Config file C:\Documents and Settings\Administrador\Datos de programa\cabal\config not found.
      Writing default configuration to C:\Documents and Settings\Administrador\Datos de 
      programa\cabal\config
      Downloading the latest package list from hackage.haskell.org

Instalando Biblioteca HPDF

Ejecutamos la siguiente orden, y si el paquete tiene alguna dependencia cabal se las descargará y las intalará:

     >cabal install hpdf

Para comprobar ver que paquetes tenemos instalados y comprobar si nuestra biblioteca está en la lista ejecutamos la siguiente orden:

     >ghc-pkg list
     C:/ghc/ghc-6.10.4\package.conf:
     Cabal-1.6.0.3, HPDF-1.4.2, HUnit-1.2.0.3, QuickCheck-1.2.0.0,
     Win32-2.2.0.0, array-0.2.0.0, base-3.0.3.1, base-4.1.0.0,
     binary-0.5.0.2, bytestring-0.9.1.4, containers-0.2.0.1,
     directory-1.0.0.3, (dph-base-0.3), (dph-par-0.3),
     (dph-prim-interface-0.3), (dph-prim-par-0.3), (dph-prim-seq-0.3),
     (dph-seq-0.3), extensible-exceptions-0.1.1.0, filepath-1.1.0.2,
     (ghc-6.10.4), ghc-prim-0.1.0.0, haddock-2.4.2, haskell-src-1.0.1.3,
     haskell98-1.0.1.0, hpc-0.5.0.3, html-1.0.1.2, integer-0.1.0.1,
     mtl-1.1.0.2, network-2.2.1.2, old-locale-1.0.0.1, old-time-1.0.0.2,
     packedstring-0.1.0.1, parallel-1.1.0.1, parsec-2.1.0.1,
     pretty-1.0.1.0, process-1.0.1.1, random-1.0.0.1,
     regex-base-0.72.0.2, regex-compat-0.71.0.1, regex-posix-0.72.0.3,
     rts-1.0, stm-2.1.1.2, syb-0.1.0.1, template-haskell-2.3.0.1,
     time-1.1.4, xhtml-3000.2.0.1, zlib-0.5.2.0

Estructura

Módulos

Los módulos y funciones que contiene esta biblioteca son los siguientes:

o Graphics.PDF:

  	Graphics.PDF.Action
  	Graphics.PDF.Annotation 
            newAnnotation :: (PdfObject a, AnnotationObject a) => a -> Draw ()
  	Graphics.PDF.Colors
            setRGBColorSpace :: Draw ()
            fillColor :: MonadPath m => Color -> m ()
            strokeColor :: MonadPath m => Color -> m ()
            setStrokeAlpha :: Double -> Draw ()
            setFillAlpha :: Double -> Draw ()
            hsvToRgb :: (Double, Double, Double) -> (Double, Double, Double)
  	Graphics.PDF.Coordinates
            toRadian :: Angle -> PDFFloat
            dot :: RealFloat t => Complex t -> Complex t -> t
            scalePt :: RealFloat t => t -> Complex t -> Complex t
            project :: RealFloat t => Complex t -> Complex t -> Complex t
            projectX :: RealFloat t => Complex t -> Complex t
            projectY :: RealFloat t => Complex t -> Complex t
            pointMatrix :: Point -> Point -> Point -> Matrix
            transform :: Matrix -> Point -> Point
            identity :: Matrix
            rotate :: Angle -> Matrix
            translate :: Point -> Matrix
            scale :: PDFFloat -> PDFFloat -> Matrix
            spiral :: Point -> Matrix
  	Graphics.PDF.Document
            addPage :: Maybe PDFRect -> PDF (PDFReference PDFPage)
            addPageWithTransition::Maybe PDFRect->Maybe PDFFloat->Maybe PDFTransition -> PDF
            drawWithPage :: PDFReference PDFPage -> Draw a -> PDF a
            createPDFXForm::PDFFloat->PDFFloat->PDFFloat->PDFFloat->Draw a->PDF (PDFReference PDFXForm)   
  	Graphics.PDF.Hyphenate
            mkCustomLanguage :: [String] -> [String] -> HyphenationDatabase
            mkExceptions :: [String] -> MapString [Int]
            hyphenate :: HyphenationDatabase -> String -> [String]
  	Graphics.PDF.Image
            createPDFJpeg :: JpegFile -> PDF (PDFReference PDFJpeg)
            readJpegFile :: FilePath -> IO (Either String JpegFile)
            jpegBounds :: JpegFile -> (PDFFloat, PDFFloat)
  	Graphics.PDF.Navigation
            newSection :: PDFString -> Maybe Color -> Maybe OutlineStyle -> PDF () -> PDF ()
            newSectionWithPage::PDFString->Maybe Color->Maybe OutlineStyle->PDFReference PDFPage -> PDF () -> PDF () 
  	Graphics.PDF.Pattern
            createColoredTiling :: PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat -> TilingType -> Draw a -> PDF (PDFReference PDFColoredPattern) 
            createUncoloredTiling :: PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat -> TilingType -> Draw a -> PDF (PDFReference PDFUncoloredPattern)
            setColoredFillPattern :: PDFReference PDFColoredPattern -> Draw ()
            setColoredStrokePattern :: PDFReference PDFColoredPattern -> Draw ()
            setUncoloredFillPattern :: PDFReference PDFUncoloredPattern -> Color -> Draw ()
            setUncoloredStrokePattern :: PDFReference PDFUncoloredPattern -> Color -> Draw ()  
  	Graphics.PDF.Shading
            paintWithShading :: PDFShading -> Draw a -> Draw ()
            applyShading :: PDFShading -> Draw ()
  	Graphics.PDF.Shapes
            moveto :: Point -> Draw ()
            lineto :: Point -> Draw ()
            arcto :: Angle -> Point -> Draw ()
            curveto :: Point -> Point -> Point -> Draw () 
            beginPath :: Point -> Draw ()
            closePath :: Draw ()
            addBezierCubic :: Point -> Point -> Point -> Draw ()
            addPolygonToPath :: [Point] -> Draw ()
            addLineToPath :: Point -> Draw ()
            strokePath :: Draw ()
            fillPath :: Draw ()
            fillAndStrokePath :: Draw ()
            fillPathEO :: Draw ()
            fillAndStrokePathEO :: Draw ()
            setAsClipPath :: Draw ()
            setAsClipPathEO :: Draw ()   
  	Graphics.PDF.Text
            drawText :: PDFText a -> Draw a
            text :: PDFFont -> PDFFloat -> PDFFloat -> PDFString -> PDFText ()
            toPDFString :: String -> PDFString
            startNewLine :: PDFText ()
            displayText :: PDFString -> PDFText ()
            textStart :: PDFFloat -> PDFFloat -> PDFText ()
            setFont :: PDFFont -> PDFText ()
            leading :: UnscaledUnit -> PDFText ()
            charSpace :: UnscaledUnit -> PDFText ()
            wordSpace :: UnscaledUnit -> PDFText ()
            textScale :: PDFFloat -> PDFText ()
            renderMode :: TextMode -> PDFText ()
            rise :: UnscaledUnit -> PDFText ()
            setTextMatrix :: Matrix -> PDFText ()
            textWidth :: PDFFont -> PDFString -> PDFFloat
            getDescent :: PDFFont -> PDFFloat
            getHeight :: PDFFont -> PDFFloat
            ripText :: PDFFont -> PDFString -> [(PDFFloat, Char)] 
            charWidth :: PDFFont -> Char -> PDFFloat
  	Graphics.PDF.Typesetting
            displayFormattedText::ParagraphStyle ps s =>Rectangle->ps ->s ->TM ps s a->Draw a
            txt :: Style s => String -> Para s ()
            kern :: Style s => PDFFloat -> Para s ()
            addPenalty :: Int -> Para s ()
            mkLetter::(Show a, Box a, DisplayableBox a)=>BoxDimension->Maybe s->a ->Letter s
            mkDrawBox :: Draw () -> DrawBox
            forceNewLine :: Style s => Para s ()
            paragraph :: Style s => Para s a -> TM ps s a
            endPara :: Style s => Para s ()
            startPara :: Style s => Para s ()
            getParaStyle :: TM ps s ps
            setParaStyle :: ParagraphStyle ps s => ps -> TM ps s ()
            mkContainer::PDFFloat->PDFFloat ->PDFFloat ->PDFFloat ->PDFFloat ->Container ps s
            fillContainer :: (ParagraphStyle ps s, ComparableStyle ps) => VerState ps -> Container ps s -> [VBox ps s] -> (Draw (), Container ps s, [VBox ps s])
            defaultVerState :: s -> VerState s
            getBoxes :: ParagraphStyle ps s => ps -> s -> TM ps s a -> [VBox ps s]
            containerX :: Container ps s -> PDFFloat
            containerY :: Container ps s -> PDFFloat
            containerWidth :: Container ps s -> PDFFloat
            containerHeight :: Container ps s -> PDFFloat
            containerContentHeight :: Container ps s -> PDFFloat
            containerContentRightBorder :: Container ps s -> PDFFloat
            containerContentLeftBorder :: Container ps s -> PDFFloat
            containerCurrentHeight :: Container ps s -> PDFFloat
            containerContentRectangle :: Container ps s -> Rectangle
            drawTextBox :: (ParagraphStyle ps s, Style s) => PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat -> Orientation -> ps -> s -> TM ps s a -> (Rectangle, Draw ())
            setFirstPassTolerance :: PDFFloat -> TM ps s ()
            setSecondPassTolerance :: PDFFloat -> TM ps s ()
            setHyphenPenaltyValue :: Int -> TM ps s ()
            setFitnessDemerit :: PDFFloat -> TM ps s ()
            setHyphenDemerit :: PDFFloat -> TM ps s ()
            setLinePenalty :: PDFFloat -> TM ps s ()
            getFirstPassTolerance :: TM ps s PDFFloat
            getSecondPassTolerance :: TM ps s PDFFloat
            getHyphenPenaltyValue :: TM ps s Int
            getFitnessDemerit :: TM ps s PDFFloat
            getHyphenDemerit :: TM ps s PDFFloat
            getLinePenalty :: TM ps s PDFFloat
            setJustification :: Justification -> TM ps s ()
            setBaseLineSkip :: PDFFloat -> PDFFloat -> PDFFloat -> TM ps s ()
            setLineSkipLimit :: PDFFloat -> TM ps s ()
            setLineSkip :: PDFFloat -> PDFFloat -> PDFFloat -> TM ps s ()
            getBaseLineSkip :: TM ps s (PDFFloat, PDFFloat, PDFFloat)
            getLineSkipLimit :: TM ps s PDFFloat
            getLineSkip :: TM ps s (PDFFloat, PDFFloat, PDFFloat)

Ejemplos

Para ver algunos ejemplos de código que utiliza la biblioteca os recomiendo la siguiente página Ejemplo HPDF y no os olvidéis de ver el archivo demo.pdf de la página con pruebas de lo que se puede hacer con la biblioteca HPDF.

Función Principal

Esta función crea el fichero PDF como resultado de su ejecución. Mediante la función runPdf se inicia el servicio pdf. Le proporcionamos un nombre al documento, y establecemos sus propiedades (Autor, propósito, modo de página, etiqueta, preferencias de visión y compresión) y un PDFRect (rectángulo que indica el tamaño de la página). Finalmente se llama a la función encargada de la creación de las páginas y su presentación.

   main = do
   let rect = PDFRect 0 0 600 400 
   runPdf "demo.pdf" (standardDocInfo { author=toPDFString "GrupoHPDF"{-, pageMode = FullScreen-}, compressed = False}) rect $ do
       funcionPruebas

En la función funcionPruebas podŕiamos diferenciar dos partes, por un lado el contenido de la página en cuanto a parrafos se refiere, y por otro lado el tema de colores, líneas y cuadros y sus posiciones.

Textos

Texto Básico

Como primer ejemplo podemos presentar un párrafo, escrito varias veces con diferentes estilos, y algunas líneas horizontales para delimitarlo

   contenidoPagina1 = do
       paragraph texto1
       glue 20 0.33 0
       setStyle BlueStyle
       setParaStyle (BluePara 0)
       paragraph texto1
       unstyledGlue 20 0.33 0
       setStyle Normal
       setParaStyle NormalPara
       paragraph texto1

El código anterior hace lo siguiente:

Introduce en el contenedor paragraph el contenido del texto1 (Fragmento de Don Quijote) Preparamos el siguiente parrafo estableciendo un estilo para separarlo del anterior (glue), le damos un estilo al texto y al parrafo y introducimos un nuevo contenedor paragraph. Establecemos un nuevo separador, esta vez inferior con unstyleGlue y volvemos a poner el estilo de parrafo y texto normal. Introducimos otra vez un contenedor

El siguiente fragmento de código muestra cómo mostrar lo anteriormente dicho en una página pdf agregándole algunas líneas.

   page1 <- addPage Nothing
     newSection (toPDFString "Texto") Nothing Nothing $ do
       newSection (toPDFString "Texto Normal") Nothing Nothing $ do
           drawWithPage page1 $ do
               strokeColor red
               stroke $ Line 10 340 500 340
               strokeColor green
               stroke $ Line 10 265 500 265
               strokeColor blue
               stroke $ Line 10 180 500 180
               strokeColor black		
               stroke $ Line 10 100 500 50
               stroke $ Line 10 50 500 100
               stroke $ Line 10 100 500 100
               stroke $ Line 10 50 500 50
               stroke $ Line 10 50 10 100
               stroke $ Line 500 50 500 100
               displayFormattedText (Rectangle (10 :+ 0) (500 :+ 330)) NormalPara Normal contenidoPagina1

Lo primero que se hace es crear una nueva página. Y seguidamente se ubica dentro de una sección y una subsección

Luego toca dibujar en la página, para ello, iremos cambiando de color y estableciendo líneas horizontales. Para finalizar escribimos el contenidoPagina1 en la zona delimitada por el rectángulo de esas dimensiones

Podeis ver el resultado En la página de ejemplos con HPDF

Texto Loco

Vamos a denominarlo así unicamente por el estilo que usa para el texto, Crazy y SuperCrazy.

Siguiendo la línea del ejemplo anterior, podemos establecer aún más formatos y estilos al texto, e incluso modificar ciertas partes del mismo y no el conjunto completo. Para ello, debemos tener el texto fragmentado y trabajar con estas partes individualmente. Para esto, en lugar de tener un contenedor como en "TextoBasico", hemos de trabajar con secciones, podemos almacenarlas en paragraph de menor tamaño o simplemente en txt.

Como he dicho, en lugar de llamar al contenedor, iremos creándolo sobre la marcha. Tendremos un estilo normal para el primer txt. Luego aplicamos estilo negrita al segundo. Volvemos al estilo normal. Al siguiente le aplicamos un estilo creado, YellowRectStyle, que enmarca el texto dentro de un cuadro sin fondo y con líneas de color amarillo. Volvemos al normal para que se aprecie mejor los otros. Aplicamos el estilo superCrazy, que consiste en ubicar el texto por palabras delante de unas cajas irregulares de color. De nuevo normal Y terminamos con el estilo crazy que tacha el texto coloreándolo

   contenidoPagina2 = do
       paragraph $ do
               txt $ "En un lugar de la Mancha, de cuyo nombre no quiero  acordarme,"
               setStyle Bold
               txt $ " no ha mucho tiempo que vivía un hidalgo de los de lanza en astillero, adarga antigua, rocín flaco y galgo corredor. "
               setStyle Normal
               txt $ "Una olla de algo más vaca que carnero, salpicón las más noches, duelos y quebrantos los sábados, lantejas los viernes, "
               setStyle YellowRectStyle
               txt $ "algún palomino de añadidura los domingos, consumían las tres partes de su hacienda.  "
               setStyle Normal
               txt $ "El resto della concluían sayo de velarte, calzas de velludo para las fiestas, "
               setStyle superCrazy
               txt $ " con sus pantuflos de lo mesmo, "
               setStyle Normal
               txt $ "y los días de entresemana se honraba con su vellorí de lo más fino."
               setStyle Crazy
               texto1
               setStyle Normal

Con esto ya tenemos el contenido de la nueva página, ahora solo queda mostrarla y darle ciertos detalles, por ejemplo un dibujo sencillo con líneas de color verde.

Para ello, creamos una nueva página y una sección. Colocamos una línea roja encima de todo y 4 líneas verdes formando el dibujo anteriormente citado.

   page2 <- addPage Nothing
       newSection (toPDFString "Texto Debug") Nothing Nothing $ do

drawWithPage page2 $ do

               strokeColor red
               stroke $ Line 150 310 550 310
               strokeColor green		
               stroke $ Line 75 300 40 280
               stroke $ Line 40 280 110 230
               stroke $ Line 110 230 60 100
               stroke $ Line 60 100 140 180
               displayFormattedText (Rectangle (150 :+ 10) (550 :+ 300)) NormalPara Normal contenidoPagina2

Podeis ver el resultado En la página de ejemplos con HPDF

Texto Circular

Para este ejemplo vamos a hacer que el texto tome forma circular. las funciones setLineSkip, setBaseLineSkip y setLineSkipLimit configuran el tamaño y forma del círculo. Con la funcion mapM simplemente hacemos que el texto se muestre 2 veces y se le añade una parte del tercero para que el círculo quede completamente lleno

   contenidoPagina3 = do
       setStyle Normal
       setLineSkip 0 0 0
       setBaseLineSkip 0 0 0
       setLineSkipLimit 0
       paragraph $ do
           mapM_ (const texto1) ([1..2]::[Int])
           txt $ "texto para rellenar"

Para mostrarlo como nueva página, haremos que el contenidoPagina3 se muestre con el formato de párrafo CirclePara y lo introducimos en el rectángulo r, en el cual queremos que se muestre

   page3 <- addPage Nothing
       newSection (toPDFString "Texto Circular") Nothing Nothing $ do
           drawWithPage page3 $ do
               let r = (Rectangle (160 :+ 65) (440 :+ 330))
               displayFormattedText r CirclePara Normal contenidoPagina3
               strokeColor red   
               stroke r

Podeis ver el resultado En la página de ejemplos con HPDF

Alineación de Texto

En esta ocasión vamos a mostrar cómo se pueden alinear el texto a la izquierda, derecha, centro o justificado. Esta vez, el contenido de la página debe ir enmarcado dentro de un estilo de párrafo concreto, por lo que hay que indicarselo con los ::.

Salvo eso, es todo igual con la excepción de que vamos a forzar un salto de línea.

   contenidoPagina4saltolinea :: TM StandardParagraphStyle StandardStyle () 
   contenidoPagina4saltolinea = do
       paragraph $ do
           txt $ "En un lugar de la Mancha, de cuyo nombre no quiero  acordarme, no ha mucho tiempo que vivía un hidalgo de los de lanza en astillero, adarga antigua, rocín flaco y galgo corredor."
           forceNewLine
           txt $ "Una olla de algo más vaca que carnero, salpicón las más noches, duelos y ..."

Para mostrarlo, se crea una nueva página, y se muestra el texto formateado, en el cuadro correspondiente y con la justificación deseada

   page4 <- addPage Nothing
       newSection (toPDFString "Texto Debug") Nothing Nothing $ do
           drawWithPage page4 $ do
               strokeColor $ Rgb 0.2 0.6 0.8
               fillColor green
               stroke $ Rectangle (50 :+ 320) (500 :+ 390)
               displayFormattedText (Rectangle (60 :+ 320) (390 :+ 380)) NormalParagraph (Font (PDFFont Times_Roman 10) green green) $ do
               setJustification FullJustification 
               contenidoPagina4saltolinea

Ampliando un poco el código, podeis ver el resultado En la página de ejemplos con HPDF

Figuras

Elipse

Esta función consiste en crear una elipse sin relleno, sólo se le asigna un borde con stroke y se le da un color que este caso es azul.

   elipse :: PDFReference PDFPage -> PDF ()
   elipse pagina = do
        drawWithPage pagina $ do
        strokeColor blue
        stroke $ Ellipse 0 0 600 300

Como podemos observar esta función recibe la referenica a una página de PDF y devuelve un PDF. Por ejemplo la llamada de esta función dentro de la función principal sería así:

       pagina1 <- addPage Nothing
       newSectionWithPage (toPDFString "Painting") Nothing Nothing pagina1 $ do
           elipse pagina1

Ampliando un poco el código, podeis ver el resultado En la página de ejemplos con HPDF


Dibujo y relleno de rectángulo y elipse

La siguiente página dibujará varias figuras en ella, haciendo uso del estilo de línea

   contenidoPagina5 :: Draw()
   contenidoPagina5 = do
   strokeColor red
   fillColor blue 
   stroke $ Rectangle (10 :+ 10) (200 :+ 100) 
   fill $ Ellipse 110 100 300 200
   fillAndStroke $ RoundRectangle 32 32 300 10 590 150
   setWidth 10
   setDash $ DashPattern [5] 0
   fillAndStroke $ RoundRectangle 200 200 200 200 590 390

Luego simplemente debemos dibujar el contenido en la página. Se puede ver el resultado aquí: En la página de ejemplos con HPDF


Otra cosa que podemos realizar en relación a lo anterior, es indicar la sección de una página que queremos mostrar, por ejemplo asi:

   page6 <- addPage Nothing
   newSection (toPDFString "Reusar Figura") Nothing Nothing $ do
   r <- createPDFXForm 50 0 300 300 contenidoPagina5
   drawWithPage page6 $ do
   drawXObject r

El resultado aquí: En la página de ejemplos con HPDF

Dibujo con patrones

Este ejemplo trata de mostrar cómo realizar un patrón y mostrar posteriormente únicamente el área imprimible deseada. El patrón se puede crear con crear con "createUncoloredTiling o con createColoredTiling", la única diferencia es que a una hay que especificarle el color antes de dibujarla y a la otra no.

   page7 <- addPage Nothing
   newSection (toPDFString "Dibujo con patrones") Nothing Nothing $ do
       p <- createUncoloredTiling 0 0 100 50 102 52 ConstantSpacing pattern
       cp <- createColoredTiling 0 0 100 50 102 52 ConstantSpacing cpattern
       drawWithPage page7 $ do  
           strokeColor green
           setUncoloredFillPattern p (Rgb 1 0 0)
           fillAndStroke $ Rectangle (250 :+ 100) (500 :+ 300)
           setColoredFillPattern cp
           fillAndStroke $ Ellipse 0 0 300 400
       where 
           pattern = do
               --stroke (Ellipse 0 0 100 50)
               stroke (Rectangle (0 :+ 0)(100 :+ 50))
           cpattern = do
               strokeColor (Rgb 1 1 0)
               stroke (Ellipse 0 0 100 50) 

En este caso hemos creado dos patrones, uno elíptico y otro rectangular, posteriormente, creamos un rectángulo y una elipse en una zona delimitada para mostrar uno de los patrones en cada una de ellas. Podemos apreciar, que existe una zona común, la cuál si descomentamos la linea y comentamos la siguiente, observaremos que los colores se sobreponen.

Podeis ver el resultado aquí. En la página de ejemplos con HPDF

Relleno con Degradado

En esta ocasión el ejemplo trata de mostrar cómo rellenar una figura con degradado, el proceso es muy simple, simplemente se selecciona el tipo de degradado (axial o radial), se modifican los parámetros para su configuración, se indican dos colores para el degradado y se añade la figura que se rellenará.

   page8 <- addPage Nothing
   newSection (toPDFString "Figuras Planas") Nothing Nothing $ do
       drawWithPage page8 $ do
           paintWithShading (RadialShading 40 260 50 0 0 500 (Rgb 1 1 0) (Rgb 1 0 0)) (addShape $ Rectangle 0 (300 :+ 300))
           paintWithShading (AxialShading 100 300 600 400 (Rgb 0 1 1) (Rgb 1 0 1)) (addShape $ Ellipse 100 300 600 400)

Podeis ver el resultado aquí. En la página de ejemplos con HPDF

Media

Imágenes

Este fragmento de código dibuja una imágen cargada previamente en el documento pdf. Existen diversas funciones para uso, entre ellas sefFillAlpha para darle transparencia, translate para desplazarla desde la posición 0 0, scale, rotate...

   contenidoPagina9 ::  JpegFile -> PDFReference PDFPage -> PDF ()
   contenidoPagina9 jpgf page =  do
       jpg <- createPDFJpeg jpgf
       drawWithPage page $ do
       withNewContext $ do
           setFillAlpha 0.4
           applyMatrix $ translate (10 :+ 10)
           applyMatrix $ scale 0.2 0.2
           drawXObject jpg
       withNewContext $ do
           applyMatrix $ rotate (Degree 20)
           applyMatrix $ translate (200 :+ (-30))
           applyMatrix $ scale 0.5 0.5
           drawXObject jpg

Previamente la imagen ha debido ser cargada mediante:

   Right jpg <- readJpegFile "image.jpeg" 

El resultado aquí. En la página de ejemplos con HPDF

Hiperenlace

Hiperenlace

HPDF también tiene la posibilidad de establecer enlaces a páginas web, para ello simplemente tenemos que hacer uso de las anotaciones, newAnnotation + URLLink, que crea en enlace hacia la página deseada enmarcándolo en un recuadro, se le debe proporcionar una dirección válida y un texto a mostrar. Si la dirección no es válida se redigirá a google.

   newAnnotation (URLLink (toPDFString "Go to HPDF") [10,10,140,40] "http://softwarelibre.uca.es/wikihaskell/index.php/Biblioteca_HPDF" True)
   drawText $ text (PDFFont Times_Roman 24) 10 20 (toPDFString "Go to HPDF")

Completando el código podemos ver el resultado. En la página de ejemplos con HPDF


Imagenes Complejas

Mosaico Penrose

Como muestra de lo que se puede llegar a hacer, dejo en la página de ejemplos la imagen penrose.

Esta imágen está creada directamente por el autor de la biblioteca, la podeis encontrar en el fichero de ejemplo que se ofrece junto a ésta en la página de hackage.

Bibliografía

Herramientas personales