#lang racket
(require ffi/unsafe
ffi/unsafe/alloc
ffi/unsafe/define
(prefix-in gui: racket/gui)
racket/draw
racket/draw/unsafe/cairo
racket/draw/private/local racket/draw/unsafe/pango (only-in slideshow/pict dc))
(provide (struct-out pdf-file)
page-count
page-size
render-doc-to-dc!
pdf-page->pict)
(define-ffi-definer define-poppler (ffi-lib "libpoppler-glib"))
(define _PopplerDocumentPointer (_cpointer 'PopplerDocument))
(define _PopplerPagePointer (_cpointer 'PopplerPage))
(struct pdf-file (uri pw))
(define-poppler poppler_document_new_from_file
(_fun [uri : _string]
[password : _string]
[err : _pointer = #f]
-> [return : (_or-null _PopplerDocumentPointer)]
-> (if return return (error "Could not open file " uri))))
(define (poppler_open pdf)
(define p (if (pdf-file? pdf)
pdf
(pdf-file (string-append "file:" (path->string (path->complete-path pdf))) #f)))
(poppler_document_new_from_file (pdf-file-uri p) (pdf-file-pw p)))
(define-poppler poppler_document_get_page
(_fun [doc : _PopplerDocumentPointer]
[index : _int]
-> _PopplerPagePointer))
(define-poppler poppler_document_get_n_pages
(_fun [doc : _PopplerDocumentPointer]
-> _int))
(define-poppler poppler_page_get_size
(_fun [page : _PopplerPagePointer]
[width : (_ptr o _double)]
[height : (_ptr o _double)]
-> _void
-> (list width height)))
(define-poppler poppler_page_render
(_fun [page : _PopplerPagePointer]
[cairo-context : _cairo_t]
-> _void))
(define (page-count doc)
(define d (poppler_open doc))
(begin0 (poppler_document_get_n_pages d)
(g_object_unref d)))
(define (page-size doc idx)
(define d (poppler_open doc))
(begin0 (poppler_page_get_size (poppler_document_get_page d idx))
(g_object_unref d)))
(define (render-doc-to-dc! doc page_idx dc)
(define d (poppler_open doc))
(define page (poppler_document_get_page d page_idx))
(define tr (send dc get-transformation))
(send dc in-cairo-context
(λ(cairo_ctx)
(poppler_page_render page cairo_ctx)))
(send dc set-transformation tr)
(g_object_unref d))
(define (pdf-page->pict doc page_idx)
(match-define (list width height) (page-size doc page_idx))
(dc (λ(ctx x y)
(define tr (send ctx get-transformation))
(send ctx translate x y)
(render-doc-to-dc! doc page_idx ctx)
(send ctx set-transformation tr))
width
height))