diff --git a/draw-doc/scribblings/draw/ps-setup-class.scrbl b/draw-doc/scribblings/draw/ps-setup-class.scrbl index d4a3605..e90b173 100644 --- a/draw-doc/scribblings/draw/ps-setup-class.scrbl +++ b/draw-doc/scribblings/draw/ps-setup-class.scrbl @@ -272,4 +272,81 @@ Sets the scaling factor for PostScript output. See Sets the translation (from the bottom left corner) for PostScript output. See @method[ps-setup% get-translation]. +} + +@section{Customizing PDF metadata} + +The @racket[ps-setup%] object allows customizing PDF metadata in + conjunction with @racket[pdf-dc%], including the document title, + author, and other fields. Any newly constructed instance of + @racket[pdf-dc%] will apply the following metadata fields to the + output PDF from @racket[current-ps-setup] if specified. For + PostScript output, these properties are ignored. + +@defmethod[(get-title) (or/c string? #f)]{ +Returns the title metadata field, specifying the title of a + document. +} + +@defmethod[(get-author) (or/c string? #f)]{ +Returns the author metadata field, specifying the author of a + document. +} + +@defmethod[(get-subject) (or/c string? #f)]{ +Returns the subject metadata field, specifying the subject of a + document. +} + +@defmethod[(get-keywords) (or/c string? #f)]{ +Returns the keywords metadata field, specifying the keywords + associated with a document. +} + +@defmethod[(get-creator) (or/c string? #f)]{ +Returns the creator metadata field, specifying the software that + created the document. By default, the creator is set to a string + specifying draw-lib and the current racket version. +} + +@defmethod[(get-create-date) (or/c string? #f)]{ +Returns the creation date metadata field, specifying the date and time + a document was created, in ISO 8601 format. +} + +@defmethod[(get-mod-date) (or/c string? #f)]{ +Returns the modification date metadata field, specifying the date and + time a document was modified, in ISO 8601 format. +} + +@defmethod[(set-title [title (or/c string? #f)]) void?]{ +Sets the title metadata field. See @method[ps-setup% get-title]. +} + +@defmethod[(set-author [author (or/c string? #f)]) void?]{ +Sets the author metadata field. See @method[ps-setup% get-author]. +} + +@defmethod[(set-subject [subject (or/c string? #f)]) void?]{ +Sets the subject metadata field. See @method[ps-setup% get-subject]. +} + +@defmethod[(set-keywords [keywords (or/c string? #f)]) void?]{ +Sets the keywords metadata field. See @method[ps-setup% get-keywords]. +} + +@defmethod[(set-creator [creator (or/c string? #f)]) void?]{ +Sets the creator metadata field. See @method[ps-setup% get-creator]. +} + +@defmethod[(set-create-date [create-date (or/c string? #f)]) void?]{ +Sets the creation date metadata field. See + @method[ps-setup% get-create-date]. The provided date must be in + ISO 8601 format. +} + +@defmethod[(set-mod-date [mod-date (or/c string? #f)]) void?]{ +Sets the modification date metadata field. See + @method[ps-setup% get-mod-date]. The provided date must be in + ISO 8601 format. }} diff --git a/draw-lib/racket/draw/private/post-script-dc.rkt b/draw-lib/racket/draw/private/post-script-dc.rkt index ea22e3a..420789a 100644 --- a/draw-lib/racket/draw/private/post-script-dc.rkt +++ b/draw-lib/racket/draw/private/post-script-dc.rkt @@ -15,6 +15,19 @@ (provide post-script-dc% pdf-dc%) +(define (pdf-set-all-md! s pss) + (define-syntax-rule (pdf-set-md! s pss key get-prop) + (let ([val (send pss get-prop)]) + (when val + (cairo_pdf_surface_set_metadata s key val)))) + (pdf-set-md! s pss 'CAIRO_PDF_METADATA_TITLE get-title) + (pdf-set-md! s pss 'CAIRO_PDF_METADATA_AUTHOR get-author) + (pdf-set-md! s pss 'CAIRO_PDF_METADATA_SUBJECT get-subject) + (pdf-set-md! s pss 'CAIRO_PDF_METADATA_KEYWORDS get-keywords) + (pdf-set-md! s pss 'CAIRO_PDF_METADATA_CREATOR get-creator) + (pdf-set-md! s pss 'CAIRO_PDF_METADATA_CREATE_DATE get-create-date) + (pdf-set-md! s pss 'CAIRO_PDF_METADATA_MOD_DATE get-mod-date)) + (define (make-dc-backend pdf?) (class default-dc-backend% (init [interactive #t] @@ -89,12 +102,12 @@ (values w h))] [(writer proc) (make-port-writer file)]) (values - ((if pdf? - cairo_pdf_surface_create_for_stream - cairo_ps_surface_create_for_stream) - proc - w - h) + (let ([s ((if pdf? + cairo_pdf_surface_create_for_stream + cairo_ps_surface_create_for_stream) + proc w h)]) + (when pdf? (pdf-set-all-md! s pss)) + s) file (not (output-port? fn)) writer diff --git a/draw-lib/racket/draw/private/ps-setup.rkt b/draw-lib/racket/draw/private/ps-setup.rkt index ec2769e..e48df26 100644 --- a/draw-lib/racket/draw/private/ps-setup.rkt +++ b/draw-lib/racket/draw/private/ps-setup.rkt @@ -1,5 +1,6 @@ #lang racket/base (require racket/class + (only-in racket/contract/base or/c) "syntax.rkt") (provide ps-setup% @@ -26,6 +27,9 @@ (and (string? s) (assoc s paper-sizes))) +(define default-creator-string + (string-append "draw-lib (racket " (version) " https://racket-lang.org)")) + (define ps-setup% (class object% (properties @@ -35,7 +39,14 @@ [[(symbol-in preview file printer) mode] 'file] [[(symbol-in portrait landscape) orientation] 'portrait] [[paper-name-string? paper-name] "Letter 8 1/2 x 11 in"] - [[string? preview-command] "gv"]) + [[string? preview-command] "gv"] + [[(or/c string? #f) title] #f] + [[(or/c string? #f) author] #f] + [[(or/c string? #f) subject] #f] + [[(or/c string? #f) keywords] #f] + [[(or/c string? #f) creator] default-creator-string] + [[(or/c string? #f) create-date] #f] + [[(or/c string? #f) mod-date] #f]) (define editor-margin-x 20.0) (define editor-margin-y 20.0) diff --git a/draw-lib/racket/draw/unsafe/cairo.rkt b/draw-lib/racket/draw/unsafe/cairo.rkt index f422fbc..4840c7e 100644 --- a/draw-lib/racket/draw/unsafe/cairo.rkt +++ b/draw-lib/racket/draw/unsafe/cairo.rkt @@ -26,6 +26,14 @@ (define _cairo_pattern_t (_cpointer 'cairo_pattern_t)) (define _cairo_font_options_t (_cpointer/null 'cairo_font_options_t)) (define _CGContextRef (_cpointer 'CGContextRef)) +(define _cairo_pdf_metadata_t + (_enum '(CAIRO_PDF_METADATA_TITLE + CAIRO_PDF_METADATA_AUTHOR + CAIRO_PDF_METADATA_SUBJECT + CAIRO_PDF_METADATA_KEYWORDS + CAIRO_PDF_METADATA_CREATOR + CAIRO_PDF_METADATA_CREATE_DATE + CAIRO_PDF_METADATA_MOD_DATE))) (define-cstruct _cairo_matrix_t ([xx _double*] [yx _double*] @@ -349,6 +357,8 @@ (define-cairo cairo_pdf_surface_create_for_stream _stream-surface-proc #:wrap stream-surface-allocator) +(define-cairo cairo_pdf_surface_set_metadata + (_fun _cairo_surface_t _cairo_pdf_metadata_t _string/utf-8 -> _void)) (define-cairo cairo_svg_surface_create_for_stream _stream-surface-proc #:wrap stream-surface-allocator)