From 6dd1d7381efa6d8201c0d72971bf502e124e51d8 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Sat, 19 Feb 2005 02:16:22 +0000 Subject: [PATCH] * scm/framework-pdf.scm (scm): new file * lily/include/pdf.hh (class Pdf_file): new file. * lily/pdf.cc (write_trailer): new file. --- ChangeLog | 8 + lily/grob.cc | 16 +- lily/include/pdf.hh | 72 ++++++++ lily/pdf.cc | 375 ++++++++++++++++++++++++++++++++++++++++++ lily/system.cc | 10 +- scm/framework-pdf.scm | 68 ++++++++ 6 files changed, 538 insertions(+), 11 deletions(-) create mode 100644 lily/include/pdf.hh create mode 100644 lily/pdf.cc create mode 100644 scm/framework-pdf.scm diff --git a/ChangeLog b/ChangeLog index bf4097206c..a380d52e2b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2005-02-19 Han-Wen Nienhuys + + * scm/framework-pdf.scm (scm): new file + + * lily/include/pdf.hh (class Pdf_file): new file. + + * lily/pdf.cc (write_trailer): new file. + 2005-02-18 Erlend Aasland * input/regression/color.ly: new file diff --git a/lily/grob.cc b/lily/grob.cc index e6299cf892..35aa13328b 100644 --- a/lily/grob.cc +++ b/lily/grob.cc @@ -217,7 +217,6 @@ Grob::get_stencil () const return unsmob_stencil (stil); stil = get_uncached_stencil (); - if (is_live ()) { Grob *me = (Grob*) this; @@ -232,7 +231,7 @@ Grob::get_uncached_stencil () const { SCM proc = get_property ("print-function"); - SCM stil = SCM_EOL; + SCM stil = SCM_EOL; if (ly_c_procedure_p (proc)) stil = scm_apply_0 (proc, scm_list_n (this->self_scm (), SCM_UNDEFINED)); @@ -246,6 +245,18 @@ Grob::get_uncached_stencil () const m->expr ()); stil = Stencil (m->extent_box (), expr). smobbed_copy (); } + + /* color support... see interpret_stencil_expression() for more... */ + SCM color = get_property ("color"); + if (color != SCM_EOL) + { + m = unsmob_stencil (stil); + SCM expr = scm_list_3 (ly_symbol2scm ("color"), + color, + m->expr ()); + + stil = Stencil (m->extent_box (), expr).smobbed_copy(); + } } return stil; @@ -771,6 +782,7 @@ ADD_INTERFACE (Grob, "grob-interface", "Y-extent-callback print-function extra-offset spacing-procedure " "context staff-symbol interfaces dependencies X-extent Y-extent extra-X-extent " "meta layer before-line-breaking-callback " + "color " "axis-group-parent-X " "axis-group-parent-Y " "after-line-breaking-callback extra-Y-extent minimum-X-extent " diff --git a/lily/include/pdf.hh b/lily/include/pdf.hh new file mode 100644 index 0000000000..dea015dd9d --- /dev/null +++ b/lily/include/pdf.hh @@ -0,0 +1,72 @@ +/* + pdf.hh -- declare Pdf output data structures. + + source file of the GNU LilyPond music typesetter + + (c) 2005 Han-Wen Nienhuys + +*/ + +#ifndef PDF_HH +#define PDF_HH + +#include + +#include "parray.hh" +#include "smobs.hh" + +class Pdf_object +{ + DECLARE_SMOBS(Pdf_object,); + bool written_; + int object_number_; + SCM value_; + long byte_count_; + + + static void write_dict (FILE*, SCM); + static void write_stream (FILE*, SCM); + static void write_vector (FILE*, SCM); + static void typecheck (SCM); + static String escape_string (String); + + String to_string () const; + void write_to_file (FILE*, bool) const; +public: + + bool is_indirect () const; + bool is_stream () const; + bool is_dict () const; + + Pdf_object(); + void set_value (SCM value); + + friend class Pdf_file; +}; + +class Pdf_file +{ + Link_array indirect_objects_; + Pdf_object *root_object_; + FILE *file_; + + DECLARE_SMOBS(Pdf_file,); + +protected: + void write_header (); + void write_trailer (); + + String get_string (); + +public: + void set_root_document (Pdf_object *obj); + Pdf_file (String filename); + void make_indirect (Pdf_object *obj); + void write_object (Pdf_object *obj); + void terminate(); +}; + +DECLARE_UNSMOB(Pdf_object, pdf_object); +DECLARE_UNSMOB(Pdf_file, pdf_file); + +#endif diff --git a/lily/pdf.cc b/lily/pdf.cc new file mode 100644 index 0000000000..b319e16278 --- /dev/null +++ b/lily/pdf.cc @@ -0,0 +1,375 @@ +/* + pdf.cc -- implement Pdf output routines. + + source file of the GNU LilyPond music typesetter + + (c) 2005 Han-Wen Nienhuys + +*/ + +#include "warn.hh" +#include "pdf.hh" +#include "ly-smobs.icc" + +IMPLEMENT_SMOBS(Pdf_object); +IMPLEMENT_DEFAULT_EQUAL_P(Pdf_object); +IMPLEMENT_TYPE_P(Pdf_object, "pdf-object?"); + + +Pdf_object::Pdf_object () +{ + object_number_ = 0; + value_ = SCM_BOOL_F; + written_ = false; + byte_count_ = 0; + + smobify_self (); +} + + +bool +Pdf_object::is_dict () const +{ + return scm_is_pair (value_) && scm_car (value_) == ly_symbol2scm ("dictionary"); +} + +bool +Pdf_object::is_indirect () const +{ + return object_number_ > 0; +} + +Pdf_object::~Pdf_object() +{ + +} + +void +Pdf_object::typecheck (SCM val) +{ + if (scm_is_pair (val)) + { + SCM tag = scm_car (val); + if (tag == ly_symbol2scm ("null")) + val = SCM_UNDEFINED; + else if (tag == ly_symbol2scm ("dictionary")) + { + SCM alist = scm_cdr (val); + for (SCM s = alist; scm_is_pair (alist); s = scm_cdr (s)) + { + Pdf_object *key = unsmob_pdf_object (scm_caar (s)); + Pdf_object *val = unsmob_pdf_object (scm_cdar (s)); + + if (!key || !val) + { + ly_display_scm (scm_car (s)); + error ("key and value must be PDF objects."); + } + } + } + else if (tag == ly_symbol2scm ("stream")) + { + if (!scm_is_string (scm_cdr (val))) + error ("stream argument should be string"); + } + else + { + ly_display_scm (tag); + error ("unknown tag"); + } + } + else if (scm_is_vector (val)) + { + SCM vec = val; + int len = scm_c_vector_length (vec); + for (int i = 0; i < len; i++) + { + Pdf_object *val = unsmob_pdf_object (scm_c_vector_ref (vec, i)); + if (!val) + { + ly_display_scm (scm_c_vector_ref (vec, i)); + error ("array content should be PDF object"); + } + } + } +} + +void +Pdf_object::set_value (SCM val) +{ + if (written_) + error ("Can't set value for written PDF object"); + + typecheck (val); + + value_ = val; +} + +SCM +Pdf_object::mark_smob (SCM smob) +{ + Pdf_object *p = (Pdf_object*) SCM_CELL_WORD_1 (smob); + return p->value_; +} + +int +Pdf_object::print_smob (SCM smob, SCM port, scm_print_state *) +{ + Pdf_object *obj = (Pdf_object*) SCM_CELL_WORD_1 (smob); + scm_puts ("#value_, port); + scm_puts (">", port); + return 1; +} + + +void +Pdf_object::write_dict (FILE *file, SCM alist) +{ + String str = ""; + + fputs ("<< " , file); + for (SCM s = alist; scm_is_pair (s); s = scm_cdr (s)) + { + Pdf_object *key = unsmob_pdf_object (scm_caar (s)); + Pdf_object *val = unsmob_pdf_object (scm_cdar (s)); + + assert (val && key); + + key->write_to_file (file, false); + val->write_to_file (file, false); + } + fputs (">>\n" , file); +} + +void +Pdf_object::write_vector (FILE *file, SCM vec) +{ + String str = ""; + + fputs ("[ " , file); + int len = scm_c_vector_length (vec); + for (int i = 0; i < len; i++) + { + Pdf_object *val = unsmob_pdf_object (scm_c_vector_ref (vec, i)); + assert (val); + val->write_to_file (file, false); + } + fputs ("]\n" , file); +} + + +void +Pdf_object::write_stream (FILE *file, SCM scmstr) +{ + String str = ly_scm2string (scmstr); + fprintf (file, "<< /Length %d >>\nstream\n" , str.length()); + fwrite (str.get_bytes(), str.length(), sizeof(Byte), file); + fputs ("endstream" , file); +} + +String +Pdf_object::escape_string (String str) +{ + str.substitute_char ('\\', "\\\\"); + str.substitute_char ('(', "\\("); + str.substitute_char (')', "\\)"); + return str; +} + +String +Pdf_object::to_string () const +{ + if (value_ == SCM_BOOL_F) + return "false"; + else if (value_ == SCM_UNDEFINED) + return "null"; + else if (value_ == SCM_BOOL_T) + return "true"; + else if (scm_is_integer (value_)) + return ::to_string (scm_to_int (value_)); + else if (scm_is_number (value_)) + return ::to_string (scm_to_double (value_)); + else if (scm_is_symbol (value_)) + return "/" + ly_symbol2string (value_) ; + else if (scm_is_string (value_)) + return "(" + escape_string (ly_scm2string (value_)) + ")"; + + assert (false); +} + +void +Pdf_object::write_to_file (FILE* file, bool dump_definition) const +{ + if (is_indirect () && !dump_definition) + { + fprintf (file, "%d 0 R", object_number_); + return; + } + + if (scm_is_vector (value_)) + write_vector (file, value_); + else if (scm_is_pair (value_)) + { + SCM tag = scm_car (value_); + if (tag == ly_symbol2scm ("dictionary")) + { + write_dict (file, scm_cdr (value_)); + } + else if (tag == ly_symbol2scm ("stream")) + { + write_stream (file, scm_cdr (value_)); + } + else + { + assert (false); + } + } + else + { + String str = to_string (); + fwrite (str.get_bytes(), str.length(), sizeof(Byte), file); + + fputc (dump_definition ? '\n' : ' ', file); + return ; + } +} + +bool +Pdf_object::is_stream () const +{ + return scm_is_pair (value_) && scm_car (value_) == ly_symbol2scm ("stream"); +} + +/****************************************************************/ + + +IMPLEMENT_SMOBS(Pdf_file); +IMPLEMENT_DEFAULT_EQUAL_P(Pdf_file); +IMPLEMENT_TYPE_P(Pdf_file, "pdf-file?"); + + +Pdf_file::Pdf_file (String name) +{ + char const *cp = name.to_str0 (); + root_object_ = NULL; + file_ = fopen (cp, "w"); + if (!file_) + { + error (_f ("Can't open file %s", cp)); + } + write_header (); + smobify_self (); +} + +void +Pdf_file::write_header () +{ + fputs ("%PDF-1.3\n", file_); +} + +void +Pdf_file::make_indirect (Pdf_object *obj) +{ + assert (!obj->is_indirect()); + + /* + Skip 0 , the null object. + */ + obj->object_number_ = indirect_objects_.size() + 1; + indirect_objects_.push (obj); +} + +void +Pdf_file::write_object (Pdf_object *obj) +{ + assert (!obj->written_); + if (obj->is_stream() && !obj->is_indirect ()) + { + make_indirect (obj); + } + + if (obj->is_indirect()) + { + obj->byte_count_ = ftell (file_); + fprintf (file_, "%d obj\n", obj->object_number_); + } + + obj->write_to_file (file_, true); + obj->written_ = true; + + if (obj->is_indirect ()) + { + fprintf (file_, " \nendobj\n"); + } +} + +void +Pdf_file::terminate () +{ + for (int i = 0; i < indirect_objects_.size (); i++) + { + if (!indirect_objects_[i]->written_) + write_object (indirect_objects_[i]); + } + + write_trailer (); + fclose (file_); + file_ = NULL; +} + +Pdf_file::~Pdf_file() +{ +} + + +void +Pdf_file::set_root_document (Pdf_object*obj) +{ + if (root_object_) + { + error ("Can have only one root object"); + } + + root_object_ = obj; + if (!obj->is_indirect ()) + { + make_indirect (obj); + } +} + +void +Pdf_file::write_trailer () +{ + long xref_offset = ftell (file_); + fprintf (file_, "xref\n%d %d\n", 0, indirect_objects_.size() + 1); + + char const *xref_entry = "%010d %05d %c \n"; + fprintf (file_, xref_entry, 0, 65535, 'f'); + for (int i = 0; i < indirect_objects_.size(); i++) + { + fprintf (file_, xref_entry, indirect_objects_[i]->byte_count_, 0, 'n'); + } + + fprintf (file_, "trailer\n<< /Size %d /Root %d 0 R >>", + indirect_objects_.size () + 1, (root_object_) ? root_object_->object_number_ : 0); + fprintf (file_, "\nstartxref\n%d\n", xref_offset); + fputs ("%%EOF", file_); +} + + +SCM +Pdf_file::mark_smob (SCM f) +{ + Pdf_file *pfile = (Pdf_file*) SCM_CELL_WORD_1(f); + for (int i = 0; i < pfile->indirect_objects_.size(); i++) + scm_gc_mark (pfile->indirect_objects_[i]->self_scm()); + return SCM_BOOL_F; +} + +int +Pdf_file::print_smob (SCM pdf, SCM port, scm_print_state*) +{ + scm_puts ("#", port); + return 1; +} diff --git a/lily/system.cc b/lily/system.cc index 7b8ff68349..d667bdd2a0 100644 --- a/lily/system.cc +++ b/lily/system.cc @@ -395,15 +395,7 @@ System::get_line () Stencil st = *stil; st.translate (o + extra); - /* color support... see interpret_stencil_expression() for more... */ - SCM color = g->get_property ("color"); - if (color != SCM_EOL) - { - SCM tmp = scm_list_3 (ly_symbol2scm ("color"), color, st.expr ()); - *tail = scm_cons (tmp, SCM_EOL); - } - else - *tail = scm_cons (st.expr (), SCM_EOL); + *tail = scm_cons (st.expr (), SCM_EOL); tail = SCM_CDRLOC(*tail); } diff --git a/scm/framework-pdf.scm b/scm/framework-pdf.scm new file mode 100644 index 0000000000..02b12d9713 --- /dev/null +++ b/scm/framework-pdf.scm @@ -0,0 +1,68 @@ +;; WIP + +(define-module (scm framework-pdf)) + +(use-modules (ice-9 regex) + (ice-9 string-fun) + (ice-9 format) + (guile) + (srfi srfi-1) + (srfi srfi-13) + (lily)) + +(define framework-pdf-module (current-module)) + +(define (stderr string . rest) + (apply format (cons (current-error-port) (cons string rest))) + (force-output (current-error-port))) + +;;(define pdebug stderr) +(define (pdebug . rest) #f) + +(define (pdf-ify lst) + (cond + ((pair? lst) + (cons (pdf-ify (car lst)) (pdf-ify (cdr lst)))) + ((vector? lst) + (vector-for-each pdf-ify lst)) + ((ly:pdf-object? lst) lst) + ((or + (string? lst) + (number? lst) + (symbol? lst)) + (pdf-ify lst)) + + (else + (ly:make-pdf-object '(null))) + + )) + +(define (make-page-object parent contents) + (ly:make-pdf-object + (cons 'dictionary + (pdf-ify + `((Type . Page) + (Parent . ,parent) + (Contents . ,contents) + ))))) + +(define (make-page-node root) ) + + +(define-public (output-framework basename book scopes fields) + (let* ((filename (format "~a.pdf" basename)) + (pdf (ly:open-pdf-file filename)) + (outputter + (ly:make-paper-outputter (format "~a.bla.pdf" basename) "pdf")) + + + + (paper (ly:paper-book-paper book)) + (pages (ly:paper-book-pages book)) + (landscape? (eq? (ly:output-def-lookup paper 'landscape) #t)) + (page-number (1- (ly:output-def-lookup paper 'firstpagenumber))) + (page-count (length pages)) + (port (ly:outputter-port outputter)))) + + +)) -- 2.39.5