2 pdf.cc -- implement Pdf output routines.
4 source file of the GNU LilyPond music typesetter
6 (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
12 #include "ly-smobs.icc"
14 IMPLEMENT_SMOBS (Pdf_object);
15 IMPLEMENT_DEFAULT_EQUAL_P (Pdf_object);
16 IMPLEMENT_TYPE_P (Pdf_object, "pdf-object?");
19 Pdf_object::Pdf_object ()
29 Pdf_object::~Pdf_object ()
35 Pdf_object::is_dict () const
37 return scm_is_pair (value_)
38 && scm_car (value_) == ly_symbol2scm ("dictionary");
42 Pdf_object::is_indirect () const
44 return object_number_ > 0;
49 Pdf_object::typecheck (SCM val)
51 if (scm_is_pair (val))
53 SCM tag = scm_car (val);
54 if (tag == ly_symbol2scm ("null"))
56 else if (tag == ly_symbol2scm ("dictionary"))
58 SCM alist = scm_cdr (val);
59 for (SCM s = alist; scm_is_pair (alist); s = scm_cdr (s))
61 Pdf_object *key = unsmob_pdf_object (scm_caar (s));
62 Pdf_object *val = unsmob_pdf_object (scm_cdar (s));
66 ly_display_scm (scm_car (s));
67 error ("key and value must be PDF objects.");
71 else if (tag == ly_symbol2scm ("stream"))
73 if (!scm_is_string (scm_cdr (val)))
74 error ("stream argument should be string");
79 error ("unknown tag");
82 else if (scm_is_vector (val))
85 int len = scm_c_vector_length (vec);
86 for (int i = 0; i < len; i++)
88 Pdf_object *val = unsmob_pdf_object (scm_c_vector_ref (vec, i));
91 ly_display_scm (scm_c_vector_ref (vec, i));
92 error ("array content should be PDF object");
99 Pdf_object::set_value (SCM val)
102 error ("Can't set value for written PDF object");
110 Pdf_object::mark_smob (SCM smob)
112 Pdf_object *p = (Pdf_object*) SCM_CELL_WORD_1 (smob);
117 Pdf_object::print_smob (SCM smob, SCM port, scm_print_state *)
119 Pdf_object *obj = (Pdf_object*) SCM_CELL_WORD_1 (smob);
120 scm_puts ("#<Pdf_object ", port);
121 scm_display (obj->value_, port);
122 scm_puts (">", port);
128 Pdf_object::write_dict (FILE *file, SCM alist)
132 fputs ("<< " , file);
133 for (SCM s = alist; scm_is_pair (s); s = scm_cdr (s))
135 Pdf_object *key = unsmob_pdf_object (scm_caar (s));
136 Pdf_object *val = unsmob_pdf_object (scm_cdar (s));
140 key->write_to_file (file, false);
141 val->write_to_file (file, false);
143 fputs (">>\n" , file);
147 Pdf_object::write_vector (FILE *file, SCM vec)
152 int len = scm_c_vector_length (vec);
153 for (int i = 0; i < len; i++)
155 Pdf_object *val = unsmob_pdf_object (scm_c_vector_ref (vec, i));
157 val->write_to_file (file, false);
159 fputs ("]\n" , file);
164 Pdf_object::write_stream (FILE *file, SCM scmstr)
166 String str = ly_scm2string (scmstr);
167 fprintf (file, "<< /Length %d >>\nstream\n" , str.length ());
168 fwrite (str.get_bytes (), str.length (), sizeof (Byte), file);
169 fputs ("endstream" , file);
173 Pdf_object::escape_string (String str)
175 str.substitute_char ('\\', "\\\\");
176 str.substitute_char ('(', "\\(");
177 str.substitute_char (')', "\\)");
182 Pdf_object::to_string () const
184 if (value_ == SCM_BOOL_F)
186 else if (value_ == SCM_UNDEFINED)
188 else if (value_ == SCM_BOOL_T)
190 else if (scm_is_integer (value_))
191 return ::to_string (scm_to_int (value_));
192 else if (scm_is_number (value_))
193 return ::to_string (scm_to_double (value_));
194 else if (scm_is_symbol (value_))
195 return "/" + ly_symbol2string (value_);
196 else if (scm_is_string (value_))
197 return "(" + escape_string (ly_scm2string (value_)) + ")";
203 Pdf_object::write_to_file (FILE* file, bool dump_definition) const
205 if (is_indirect () && !dump_definition)
207 fprintf (file, "%d 0 R", object_number_);
211 if (scm_is_vector (value_))
212 write_vector (file, value_);
213 else if (scm_is_pair (value_))
215 SCM tag = scm_car (value_);
216 if (tag == ly_symbol2scm ("dictionary"))
217 write_dict (file, scm_cdr (value_));
218 else if (tag == ly_symbol2scm ("stream"))
219 write_stream (file, scm_cdr (value_));
225 String str = to_string ();
226 fwrite (str.get_bytes (), str.length (), sizeof (Byte), file);
228 fputc (dump_definition ? '\n' : ' ', file);
234 Pdf_object::is_stream () const
236 return scm_is_pair (value_) && scm_car (value_) == ly_symbol2scm ("stream");
239 /****************************************************************/
242 IMPLEMENT_SMOBS (Pdf_file);
243 IMPLEMENT_DEFAULT_EQUAL_P (Pdf_file);
244 IMPLEMENT_TYPE_P (Pdf_file, "pdf-file?");
247 Pdf_file::Pdf_file (String name)
249 char const *cp = name.to_str0 ();
251 file_ = fopen (cp, "w");
253 error (_f ("can't open file: `%s'", cp));
258 Pdf_file::~Pdf_file ()
263 Pdf_file::write_header ()
265 fputs ("%PDF-1.3\n", file_);
269 Pdf_file::make_indirect (Pdf_object *obj)
271 assert (!obj->is_indirect ());
274 Skip 0 , the null object.
276 obj->object_number_ = indirect_objects_.size () + 1;
277 indirect_objects_.push (obj);
281 Pdf_file::write_object (Pdf_object *obj)
283 assert (!obj->written_);
284 if (obj->is_stream () && !obj->is_indirect ())
287 if (obj->is_indirect ())
289 obj->byte_count_ = ftell (file_);
290 fprintf (file_, "%d obj\n", obj->object_number_);
293 obj->write_to_file (file_, true);
294 obj->written_ = true;
296 if (obj->is_indirect ())
297 fprintf (file_, " \nendobj\n");
301 Pdf_file::terminate ()
303 for (int i = 0; i < indirect_objects_.size (); i++)
305 if (!indirect_objects_[i]->written_)
306 write_object (indirect_objects_[i]);
315 Pdf_file::set_root_document (Pdf_object*obj)
318 error ("Can have only one root object");
321 if (!obj->is_indirect ())
326 Pdf_file::write_trailer ()
328 long xref_offset = ftell (file_);
329 fprintf (file_, "xref\n%d %d\n", 0, indirect_objects_.size () + 1);
331 char const *xref_entry = "%010d %05d %c \n";
332 fprintf (file_, xref_entry, 0, 65535, 'f');
333 for (int i = 0; i < indirect_objects_.size (); i++)
334 fprintf (file_, xref_entry, indirect_objects_[i]->byte_count_, 0, 'n');
336 fprintf (file_, "trailer\n<< /Size %d /Root %d 0 R >>",
337 indirect_objects_.size () + 1,
338 (root_object_) ? root_object_->object_number_ : 0);
339 fprintf (file_, "\nstartxref\n%d\n", xref_offset);
340 fputs ("%%EOF", file_);
344 Pdf_file::mark_smob (SCM f)
346 Pdf_file *pfile = (Pdf_file*) SCM_CELL_WORD_1 (f);
347 for (int i = 0; i < pfile->indirect_objects_.size (); i++)
348 scm_gc_mark (pfile->indirect_objects_[i]->self_scm ());
353 Pdf_file::print_smob (SCM pdf, SCM port, scm_print_state*)
355 scm_puts ("#<PDF file>", port);