1 /*
2 * << H a r u --free pdf library >> -- DocMaker.cpp
3 *
4 * Copyright (c) 1999-2002 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
5 *
6 * Permission to use, copy, modify, distribute and sell this software
7 * and its documentation for any purpose is hereby granted without fee,
8 * provided that the above copyright notice appear in all copies and
9 * that both that copyright notice and this permission notice appear
10 * in supporting documentation.
11 * It is provided "as is" without express or implied warranty.
12 *
13 * 2002.10.21 create.
14 *
15 * %T<title> <VERSION> <DATE>
16 * --- Add front page with specified parameters.
17 * %S<title> <section-no> --- Add section named <title> with level n.
18 * %I<title> <image-file-name> <width> <height>
19 * --- Insert image file.
20 * %W<title> <WMF-file-name> <width> <height>
21 * --- Insert WMF file with specified size.
22 * other --- Show text at current position.
23 *
24 */
25
26 #include <assert.h>
27 #include "libharu.h"
28 #include "libharu_wmf.h"
29
30 #define LEFT_MARGIN 85
31 #define RIGHT_MARGIN LEFT_MARGIN
32 #define TOP_MARGIN 50
33 #define BOTTOM_MARGIN TOP_MARGIN + 10
34 #define IMAGE_SPACE 20
35 #define PAGE_WIDTH 530
36 #define PAGE_HEIGHT 665
37
38 const double BASE_RIGHT = PAGE_WIDTH - RIGHT_MARGIN;
39 const double BASE_TOP = PAGE_HEIGHT - TOP_MARGIN;
40
41 static const int PDF_CHAR_SIZE_TITLE0 = 35;
42 static const int PDF_CHAR_SIZE_TITLE1 = 18;
43 static const int PDF_CHAR_SIZE_TITLE2 = 10;
44 static const int PDF_CHAR_SIZE_TITLE3 = 10;
45 static const int PDF_CHAR_SIZE_DEFAULT = 10;
46 static const int PDF_CHAR_SIZE_SMALL = 8;
47
48 class DocMaker;
49
50 class DocIndex
51 {
52 friend class DocMaker;
53 public:
54 DocIndex(int level, const char* title,
55 PdfDestination* desti, int page, int chapter1,
56 int chapter2);
57 ~DocIndex();
58 private:
59 PdfDestination* fDest;
60 char* fTitle;
61 int fPage;
62 int fLevel;
63 int fChapter[2];
64 };
65
66 class DocMaker
67 {
68 public:
69 DocMaker();
70 ~DocMaker();
71 void WriteBackground(PdfContents* canvas);
GetCurrent()72 PdfPage* GetCurrent() { return fContentsPage; }
GetCurrentIdx()73 PdfPage* GetCurrentIdx() { return fIndexPage; }
74 void AddTitle(const char* buf);
75 void AddSection(const char* title, int level);
76 void ShowText(const char* text);
77 void ShowImage(const char* title, const char* filename,
78 double width = 0, double height = 0);
79 void ShowWMFImage(const char* title, const char* filename,
80 double width = 0, double height = 0);
WriteToFile(const char * filename)81 void WriteToFile(const char* filename)
82 { fDoc->WriteToFile(filename); }
83 const char* GetStrParam(const char* str, char* param, int len);
84 const char* GetIntParam(const char* str, int* param);
85 const char* GetFloatParam(const char* str, double* param);
86 void MakeIndex();
87 void MakeOutline();
88 void SetDocName(const char* docname);
89 void SetFont(const char* name);
90 void SetIndent(int level);
91 void ShowLabel(const char* text, int indent);
CurLine()92 int CurLine() { return fCurLine; }
IncCurLine()93 void IncCurLine() { fCurLine++; }
94 void IncLine();
95 private:
96 void DrawPageBack(PdfContents* canvas, double top,
97 bool show_pageno = true);
98 void AddIndexPage();
99 void AddPage();
100 PdfDoc* fDoc;
101 PdfContents* fCanvas;
102 PdfPages* fContentsPages;
103 PdfPages* fFrontPages;
104 PdfPage* fFrontPage;
105 PdfPages* fIndexPages;
106 PdfPage* fContentsPage;
107 PdfDestination* fContentsDst;
108 PdfPage* fIndexPage;
109 int fSection[3];
110 int fFigureNo;
111 int fImageNo;
112 double fIndexYPos;
113 double fPageYPos;
114 int fXMargine;
115 char fCurFont[64];
116 int fCurFontSize;
117 int fPage;
118 char fTitle[256];
119 char* fDocName;
120 int fImageIdx;
121 double fTmpXPos;
122 double fTmpYPos;
123 double fLeftMargin;
124 bool fAdjustFlg;
125 PdfList* fIndexes;
126 int fCurLine;
127 };
128
DocIndex(int level,const char * title,PdfDestination * dest,int page,int chapter_1,int chapter_2)129 DocIndex::DocIndex(int level, const char* title, PdfDestination* dest,
130 int page, int chapter_1, int chapter_2)
131 {
132 int len = strlen(title);
133 fTitle = new char[len + 1];
134 strncpy(fTitle, title, len);
135 fTitle[len] = 0x00;
136 fDest = dest;
137 fPage = page;
138 fLevel = level;
139 fChapter[0] = chapter_1;
140 fChapter[1] = chapter_2;
141 }
142
143
~DocIndex()144 DocIndex::~DocIndex()
145 {
146 if (fTitle != NULL)
147 delete[] fTitle;
148 }
149
DocMaker()150 DocMaker::DocMaker()
151 {
152 fDoc = new PdfDoc;
153 fDoc->NewDoc();
154
155 PDF_DEBUG_PRINT(("DocMaker::DocMaker()\n"));
156
157 /* Set PageMode and PageLayout. */
158 fDoc->Catalog()->SetPageMode(PDF_USE_OUTLINES);
159 fDoc->Catalog()->SetPageLayout(PDF_ONE_COLUMN);
160 fDoc->Catalog()->AddPageLabel(0, PDF_PAGE_NUM_LOWER_ROMAN);
161 fDoc->RootPages()->SetSize(PAGE_WIDTH, PAGE_HEIGHT);
162
163 PdfInfo* info = fDoc->Info();
164 info->SetCreator("DocMaker");
165
166 time_t ct = time(NULL);
167 struct tm* lst = localtime(&ct);
168 pdf_date date = {lst->tm_year + 1900, lst->tm_mon + 1, lst->tm_mday,
169 lst->tm_hour, lst->tm_min, lst->tm_sec, '-', 0, 0};
170
171 info->SetCreationDate(date);
172
173 /* Create Pages objects. */
174 PDF_DEBUG_PRINT(("DocMaker::DocMaker() --create pages\n"));
175 fFrontPages = fDoc->RootPages()->AddPages();
176 fIndexPages = fDoc->RootPages()->AddPages();
177 fContentsPages = fDoc->RootPages()->AddPages();
178
179 /* Create Font objects. */
180 PDF_DEBUG_PRINT(("DocMaker::DocMaker() --create fonts\n"));
181 PdfType1FontDef* fd = new PdfHelveticaFontDef();
182 PdfEncodingDef* encoding = new PdfWinAnsiEncoding();
183 fDoc->AddType1Font(fd, NULL, encoding);
184
185 fd = new PdfHelveticaBoldFontDef();
186 fDoc->AddType1Font(fd, NULL, encoding);
187
188 fd = new PdfHelveticaObliqueFontDef();
189 fDoc->AddType1Font(fd, NULL, encoding);
190
191 fd = new PdfTimesRomanFontDef();
192 fDoc->AddType1Font(fd, NULL, encoding);
193
194 fd = new PdfTimesItalicFontDef();
195 fDoc->AddType1Font(fd, NULL, encoding);
196
197 fd = new PdfTimesBoldFontDef();
198 fDoc->AddType1Font(fd, NULL, encoding);
199
200 fd = new PdfCourierFontDef();
201 fDoc->AddType1Font(fd, NULL, encoding);
202
203 fd = new PdfSymbolFontDef();
204 fDoc->AddType1Font(fd);
205
206 strncpy(fCurFont, "Times-Roman", 64);
207 fCurFontSize = PDF_CHAR_SIZE_DEFAULT;
208 fLeftMargin = LEFT_MARGIN;
209 fIndexYPos = 70;
210 fSection[0] = 0;
211 fSection[1] = 0;
212 fSection[2] = 0;
213 fPage = 0;
214
215 fImageIdx = 0;
216 fDocName = NULL;
217 fFrontPage = NULL;
218 fIndexes = new PdfList();
219 fCurLine = 0;
220 PDF_DEBUG_PRINT(("DocMaker::DocMaker() --end\n"));
221 }
222
~DocMaker()223 DocMaker::~DocMaker()
224 {
225 for (int i = 0; i < fIndexes->CountItems(); i++)
226 delete (DocIndex*)fIndexes->ItemAt(i);
227
228 if (fDocName != NULL)
229 delete[] fDocName;
230
231 delete fIndexes;
232 delete fDoc;
233 }
234
235 void
MakeIndex()236 DocMaker::MakeIndex()
237 {
238 char buf[255];
239
240 PDF_DEBUG_PRINT(("DocMaker::MakeIndex()\n"));
241 AddIndexPage();
242
243 fContentsDst = new PdfDestination(fIndexPage);
244 fContentsDst->SetFit();
245
246 fCanvas = fIndexPage->Canvas();
247 fCanvas->SetFontAndSize("Helvetica-Bold", PDF_CHAR_SIZE_TITLE1);
248 fCanvas->BeginText();
249
250 double tw = fCanvas->TextWidth("Contents");
251 double xpos = (fCanvas->Width() - LEFT_MARGIN - RIGHT_MARGIN -
252 tw) / 2 + LEFT_MARGIN;
253 fCanvas->MoveTextPos(xpos, BASE_TOP - 60);
254 fCanvas->ShowText("Contents");
255 fCanvas->EndText();
256
257 fCanvas->SetFontAndSize("Helvetica-Bold", PDF_CHAR_SIZE_TITLE3);
258 fCanvas->BeginText();
259 fCanvas->MoveTextPos(LEFT_MARGIN + 60, BASE_TOP - 80);
260
261 fPageYPos = BASE_TOP - 80;
262
263 for (int i = 0; i < fIndexes->CountItems(); i++) {
264 DocIndex* idx = (DocIndex*)fIndexes->ItemAt(i);
265
266 if (idx->fLevel == 0) {
267 fCanvas->MoveTextPos(0, -25);
268 snprintf(buf, 255, "Chapter %d: %s", idx->fChapter[0],
269 idx->fTitle);
270 fCanvas->SetFontAndSize("Helvetica-Bold", PDF_CHAR_SIZE_TITLE3);
271 PdfLinkAnnot* annot = fIndexPage->AddLink(PdfRect(
272 fCanvas->TextPos().x,
273 fCanvas->TextPos().y,
274 fCanvas->TextPos().x + fCanvas->TextWidth(buf),
275 fCanvas->TextPos().y + PDF_CHAR_SIZE_TITLE3),
276 idx->fDest);
277 annot->SetBorder(0, 0, 0);
278 fCanvas->ShowText(buf);
279 fCanvas->MoveTextPos(0, -5);
280
281 fPageYPos -= 30;
282 } else {
283 fCanvas->MoveTextPos(-30, -15);
284 snprintf(buf, 255, "%d.%d", idx->fChapter[0], idx->fChapter[1]);
285 fCanvas->SetFontAndSize("Times-Roman", PDF_CHAR_SIZE_DEFAULT);
286 fCanvas->ShowText(buf);
287 fCanvas->MoveTextPos(30, 0);
288 PdfLinkAnnot* annot = fIndexPage->AddLink(PdfRect(
289 fCanvas->TextPos().x,
290 fCanvas->TextPos().y,
291 fCanvas->TextPos().x + fCanvas->TextWidth(idx->fTitle),
292 fCanvas->TextPos().y + PDF_CHAR_SIZE_DEFAULT),
293 idx->fDest);
294 annot->SetBorder(0, 0, 0);
295 fCanvas->ShowText(idx->fTitle);
296
297 fPageYPos -= 15;
298 }
299 if (fPageYPos < BOTTOM_MARGIN + PDF_CHAR_SIZE_TITLE2 * 2) {
300 fCanvas->EndText();
301 AddIndexPage();
302 fCanvas = fIndexPage->Canvas();
303 fCanvas->BeginText();
304 fCanvas->MoveTextPos(LEFT_MARGIN + 60, BASE_TOP - 60);
305 fPageYPos = BASE_TOP - 60;
306 }
307 }
308 fCanvas->EndText();
309
310 unsigned int idx_count = fIndexPages->GetKidsCount() + 1;
311 fDoc->Catalog()->AddPageLabel(idx_count, PDF_PAGE_NUM_DECIMAL);
312 }
313
314
315 void
MakeOutline()316 DocMaker::MakeOutline()
317 {
318 PDF_DEBUG_PRINT(("DocMaker::MakeOutline()\n"));
319 PdfOutlineItem* root = new PdfOutlineItem(fDoc->Outlines());
320 if (fDocName != NULL)
321 root->SetTitle(fDocName);
322 else
323 root->SetTitle("no title.");
324 root->SetOpened(true);
325 if (fFrontPage != NULL) {
326 PdfDestination* dst = new PdfDestination(fFrontPage);
327 root->SetDestination(dst);
328 fDoc->Catalog()->SetOpenAction(dst);
329 }
330
331 PdfOutlineItem* item = new PdfOutlineItem(root);
332 item->SetTitle("Contents");
333 item->SetDestination(fContentsDst);
334
335 for (int i = 0; i < fIndexes->CountItems(); i++) {
336 DocIndex* idx = (DocIndex*)fIndexes->ItemAt(i);
337
338 if (idx->fLevel == 0) {
339 char buf[255];
340 item = new PdfOutlineItem(root);
341 snprintf(buf, 255, "%d %s", idx->fChapter[0], idx->fTitle);
342 item->SetTitle(buf);
343 item->SetDestination(idx->fDest);
344 } else {
345 char buf[255];
346 PdfOutlineItem* tmp_item = new PdfOutlineItem(item);
347 snprintf(buf, 255, "%d.%d %s", idx->fChapter[0],
348 idx->fChapter[1], idx->fTitle);
349 tmp_item->SetTitle(buf);
350 tmp_item->SetDestination(idx->fDest);
351 }
352 }
353 }
354
355 void
DrawPageBack(PdfContents * canvas,double top,bool show_pageno)356 DocMaker::DrawPageBack(PdfContents* canvas, double top, bool show_pageno)
357 {
358 PDF_DEBUG_PRINT(("DocMaker::DrawPageBack()\n"));
359 try {
360 double pw = canvas->Width();
361
362 canvas->SetLineWidth(0.5);
363 canvas->MoveTo(LEFT_MARGIN, top);
364 canvas->LineTo(BASE_RIGHT, top);
365 canvas->MoveTo(LEFT_MARGIN, top + 8);
366 canvas->LineTo(LEFT_MARGIN, top - 2);
367 canvas->MoveTo(BASE_RIGHT, top + 8);
368 canvas->LineTo(BASE_RIGHT, top - 2);
369 canvas->MoveTo(pw / 2, top + 4);
370 canvas->LineTo(pw / 2, top - 2);
371 canvas->Stroke();
372
373 /* print page number */
374 if (show_pageno && fPage > 0) {
375 char tmp_page[10];
376
377 snprintf(tmp_page, 10, "%d", fPage);
378
379 canvas->BeginText();
380 canvas->SetFontAndSize("Helvetica", 8);
381 double tw = canvas->TextWidth(tmp_page);
382 canvas->MoveTextPos((pw - tw) / 2, top + 6);
383 canvas->ShowText(tmp_page);
384
385 canvas->EndText();
386 }
387 } catch (PdfException& e) {
388 fprintf(stderr, "%s\n", e.what());
389 }
390
391 return;
392 }
393
394 void
AddIndexPage()395 DocMaker::AddIndexPage()
396 {
397 PDF_DEBUG_PRINT(("DocMaker::AddIndexPage()\n"));
398 fIndexPage = fIndexPages->AddPage();
399
400 PdfContents* canvas = fIndexPage->Canvas();
401 canvas->AddFilter(PDF_FILTER_DEFLATE);
402
403 DrawPageBack(canvas, BASE_TOP, false);
404 }
405
406 void
ShowLabel(const char * text,int indent)407 DocMaker::ShowLabel(const char* text, int indent)
408 {
409 PDF_DEBUG_PRINT(("DocMaker::ShowLabel()\n"));
410 /* double sava_pos = fPageYPos; */
411 /* double sava_fsize = fCanvas->FontSize(); */
412 char save_font[64];
413 memset(save_font, 0x00, 64);
414 strncpy(save_font, fCanvas->FontName(), 63);
415
416 SetFont("Helvetica-Bold");
417 fCurFontSize -= 1;
418 SetIndent(0);
419 ShowText(text);
420 SetFont("Times-Roman");
421 fCurFontSize += 1;
422 SetIndent(indent);
423 /* fPageYPos = sava_pos - 1; */
424 fPageYPos += fCanvas->TextLeading();
425 }
426
427 void
IncLine()428 DocMaker::IncLine()
429 {
430 fPageYPos -= PDF_CHAR_SIZE_DEFAULT / 2;
431 }
432
433 void
ShowText(const char * text)434 DocMaker::ShowText(const char* text)
435 {
436 PDF_DEBUG_PRINT(("DocMaker::ShowText()\n"));
437 if (strlen(text) == 0) {
438 fPageYPos -= fCurFontSize;
439 return;
440 }
441
442 double w = fCanvas->Width() - LEFT_MARGIN - RIGHT_MARGIN;
443 const char* tmp_txt = text;
444
445 fCanvas->BeginText();
446 fCanvas->SetFontAndSize(fCurFont, fCurFontSize);
447 fCanvas->MoveTextPos(fLeftMargin, fPageYPos + (fCurFontSize - 2));
448
449 unsigned int num_char = 0;
450 char buf[1024];
451
452 while (num_char < strlen(text)) {
453
454 unsigned int nc = fCanvas->MeasureText(tmp_txt, w);
455 assert(nc < 1024);
456
457 if (fPageYPos < BOTTOM_MARGIN) {
458 fCanvas->EndText();
459 AddPage();
460 fCanvas->BeginText();
461 fCanvas->SetFontAndSize(fCurFont, fCurFontSize);
462 fCanvas->MoveTextPos(fLeftMargin, fPageYPos +
463 (fCurFontSize - 2));
464 }
465
466 memset(buf, 0x00, 1024);
467 memcpy(buf, tmp_txt, nc);
468
469 /* adjustting text widths with setting character space. */
470 if (num_char + nc < strlen(text)) {
471 double tw = fCanvas->TextWidth(buf);
472 double cs = (w - tw) / nc;
473 fCanvas->SetCharSpace(cs);
474 }
475 fCanvas->ShowTextNextLine(buf);
476 fCanvas->SetCharSpace(0);
477 fPageYPos -= fCanvas->TextLeading();
478
479 num_char += nc;
480 tmp_txt += nc;
481 }
482 fCanvas->EndText();
483 fTmpXPos = fLeftMargin;
484 fTmpYPos = 0;
485 fAdjustFlg = false;
486 }
487
488 void
AddSection(const char * title,int level)489 DocMaker::AddSection(const char* title, int level)
490 {
491 char buf[255];
492
493 PDF_DEBUG_PRINT(("DocMaker::AddSection()\n"));
494 if (level == 0) {
495 double tw;
496 double xpos;
497
498 fTitle[255] = 0x00;
499 strncpy(fTitle, title, 255);
500 fSection[0]++;
501 fSection[1] = 0;
502 fSection[2] = 0;
503 fFigureNo = 0;
504 fImageNo = 0;
505 AddPage();
506 fCanvas->SetFontAndSize("Helvetica-Bold", PDF_CHAR_SIZE_TITLE3);
507 fCanvas->BeginText();
508 snprintf(buf, 255, "CHAPTER %2d", fSection[0]);
509
510 tw = fCanvas->TextWidth(buf);
511 xpos = (fCanvas->Width() - LEFT_MARGIN - RIGHT_MARGIN -
512 tw) / 2 + LEFT_MARGIN;
513 fCanvas->MoveTextPos(xpos, BASE_TOP - 60);
514 fCanvas->ShowText(buf);
515 fCanvas->EndText();
516
517 fCanvas->MoveTo(xpos, BASE_TOP - 64);
518 fCanvas->LineTo(xpos + tw, BASE_TOP - 64);
519 fCanvas->ClosePathStroke();
520
521 fCanvas->SetFontAndSize("Helvetica-Bold", PDF_CHAR_SIZE_TITLE1);
522 fCanvas->BeginText();
523
524 tw = fCanvas->TextWidth(title);
525 xpos = (fCanvas->Width() - LEFT_MARGIN - RIGHT_MARGIN -
526 tw) / 2 + LEFT_MARGIN;
527 fCanvas->MoveTextPos(xpos, BASE_TOP - 105);
528 fCanvas->ShowText(title);
529 fCanvas->EndText();
530
531 fPageYPos = BASE_TOP - 140;
532 fAdjustFlg = false;
533 } else if (level == 1) {
534 fSection[1]++;
535 fSection[2] = 0;
536
537 if (fPageYPos < (BOTTOM_MARGIN + PDF_CHAR_SIZE_TITLE2 +
538 PDF_CHAR_SIZE_DEFAULT))
539 AddPage();
540
541 fCanvas->SetFontAndSize("Helvetica-Bold", PDF_CHAR_SIZE_TITLE2);
542 fCanvas->BeginText();
543
544 snprintf(buf, 255, "%d.%d ", fSection[0], fSection[1]);
545 if (fAdjustFlg == true)
546 fPageYPos -= PDF_CHAR_SIZE_TITLE2;
547 else
548 fPageYPos -= PDF_CHAR_SIZE_TITLE2 + 10;
549 fCanvas->MoveTextPos(LEFT_MARGIN - fCanvas->TextWidth(buf), fPageYPos);
550 fCanvas->ShowText(buf);
551 fCanvas->ShowText(title);
552 fPageYPos -= (PDF_CHAR_SIZE_TITLE2 + 5);
553
554 fCanvas->EndText();
555 fAdjustFlg = true;
556 } else {
557 fSection[2]++;
558
559 if (fPageYPos < (BOTTOM_MARGIN + PDF_CHAR_SIZE_TITLE3 +
560 PDF_CHAR_SIZE_DEFAULT))
561 AddPage();
562
563 fCanvas->SetFontAndSize("Helvetica-Bold", PDF_CHAR_SIZE_TITLE3);
564 fCanvas->BeginText();
565
566 snprintf(buf, 255, "%d.%d.%d ", fSection[0], fSection[1], fSection[2]);
567 if (fAdjustFlg == true)
568 fPageYPos -= PDF_CHAR_SIZE_TITLE3 - 5;
569 else
570 fPageYPos -= PDF_CHAR_SIZE_TITLE3 + 5;
571 fCanvas->MoveTextPos(LEFT_MARGIN - fCanvas->TextWidth(buf), fPageYPos);
572 fCanvas->ShowText(buf);
573 fCanvas->ShowText(title);
574 fPageYPos -= (PDF_CHAR_SIZE_TITLE2 + 5);
575
576 fCanvas->EndText();
577 fAdjustFlg = true;
578 }
579
580 if (level <= 1) {
581 PdfDestination* dst = new PdfDestination(fCanvas->Page());
582 if (level != 0)
583 dst->SetFitH(fPageYPos + 30);
584 DocIndex* di = new DocIndex(level, title, dst, 0, fSection[0],
585 fSection[1]);
586 fIndexes->AddItem(di);
587 }
588 SetIndent(0);
589 }
590
591 void
ShowImage(const char * title,const char * filename,double width,double height)592 DocMaker::ShowImage(const char* title, const char* filename,
593 double width, double height)
594 {
595 char s[1024];
596 double img_width;
597 double img_height;
598
599 PDF_DEBUG_PRINT(("DocMaker::ShowImage()\n"));
600 PdfPngImage* image = new PdfPngImage(fDoc);
601 image->AddFilter(PDF_FILTER_DEFLATE);
602
603 try {
604 image->LoadFromFile(filename);
605 } catch (PdfException& e) {
606 fprintf(stderr, "ERROR: failed to load image[%s].\n", filename);
607 delete image;
608 exit(1);
609 }
610 try {
611 fDoc->AddXObject(image);
612 } catch (...) {
613 delete image;
614 return;
615 }
616
617 if (width == 0)
618 img_width = image->Width();
619 else
620 img_width = width;
621
622 if (height == 0)
623 img_height = image->Height();
624 else
625 img_height = height;
626
627 if (fCanvas->Width() - RIGHT_MARGIN < fTmpXPos + img_width ||
628 fTmpYPos - img_height - 40 < fPageYPos) {
629 if (fPageYPos - img_height < BOTTOM_MARGIN + 10)
630 AddPage();
631 fTmpYPos = fPageYPos;
632 fPageYPos -= (img_height + 40);
633 fTmpXPos = LEFT_MARGIN;
634 fTmpYPos = 0;
635 }
636
637 double base_ypos = fPageYPos + 20 + PDF_CHAR_SIZE_SMALL + 4;
638
639 fCanvas->GSave();
640 fCanvas->Concat(img_width, 0, 0, img_height, fTmpXPos, base_ypos);
641 fCanvas->ExecuteXObject(image);
642 fCanvas->GRestore();
643
644 fImageNo++;
645 snprintf(s, 1024, "IMAGE %d.%d ", fSection[0], fImageNo);
646
647 fCanvas->BeginText();
648 fCanvas->SetFontAndSize("Helvetica-Bold", PDF_CHAR_SIZE_SMALL);
649 fCanvas->MoveTextPos(fTmpXPos, fPageYPos + 20);
650 fCanvas->ShowText(s);
651 fCanvas->SetFontAndSize("Times-Roman", PDF_CHAR_SIZE_DEFAULT);
652 fCanvas->ShowText(title);
653 fCanvas->EndText();
654 fCanvas->SetFontAndSize(fCurFont, fCurFontSize);
655
656 fTmpXPos += width + IMAGE_SPACE;
657 }
658
659 void
ShowWMFImage(const char * title,const char * filename,double width,double height)660 DocMaker::ShowWMFImage(const char* title, const char* filename,
661 double width, double height)
662 {
663 char s[1024];
664 double img_width;
665 double img_height;
666
667 PDF_DEBUG_PRINT(("DocMaker::ShowWMFImage()\n"));
668 img_width = width;
669 img_height = height;
670
671 if (fCanvas->Width() - RIGHT_MARGIN < fTmpXPos + img_width ||
672 fTmpYPos - img_height - 40 < fPageYPos) {
673 if (fPageYPos - img_height < BOTTOM_MARGIN + 10)
674 AddPage();
675 fTmpYPos = fPageYPos;
676 fPageYPos -= (img_height + 40);
677 fTmpXPos = LEFT_MARGIN;
678 fTmpYPos = 0;
679 }
680
681 double base_ypos = fPageYPos + 20 + PDF_CHAR_SIZE_SMALL + 4;
682
683 PdfWMFLoader* loader = new PdfWMFLoader();
684 pdf_rect rect = PdfRect(fTmpXPos, base_ypos - img_height,
685 fTmpXPos + img_width, base_ypos);
686 loader->DrawWMFImage(filename, fCanvas, rect);
687
688 fCanvas->Rectangle(fTmpXPos, base_ypos, width, height);
689 fCanvas->Stroke();
690
691 fFigureNo++;
692 snprintf(s, 1024, "IMAGE %d.%d ", fSection[0], fFigureNo);
693
694
695 fCanvas->BeginText();
696 fCanvas->SetFontAndSize("Helvetica-Bold", PDF_CHAR_SIZE_SMALL);
697 fCanvas->MoveTextPos(fTmpXPos, fPageYPos + 20);
698 fCanvas->ShowText(s);
699 fCanvas->SetFontAndSize("Times-Roman", PDF_CHAR_SIZE_DEFAULT);
700 fCanvas->ShowText(title);
701 fCanvas->EndText();
702 fCanvas->SetFontAndSize(fCurFont, fCurFontSize);
703
704 fTmpXPos += width + IMAGE_SPACE;
705 }
706
707 void
AddPage()708 DocMaker::AddPage()
709 {
710 PDF_DEBUG_PRINT(("DocMaker::AddPage()\n"));
711 fContentsPage = fContentsPages->AddPage();
712 fCanvas = fContentsPage->Canvas();
713 fCanvas->SetFontAndSize(fCurFont, fCurFontSize);
714 fCanvas->SetTextLeading(PDF_CHAR_SIZE_DEFAULT + 2);
715 fCanvas->AddFilter(PDF_FILTER_DEFLATE);
716
717 fPage++;
718 WriteBackground(fCanvas);
719
720 fPageYPos = BASE_TOP - 30;
721 fTmpXPos = LEFT_MARGIN;
722 fTmpYPos = 0;
723 }
724
725 void
WriteBackground(PdfContents * canvas)726 DocMaker::WriteBackground(PdfContents* canvas)
727 {
728 PDF_DEBUG_PRINT(("DocMaker::WriteBackground()\n"));
729 DrawPageBack(canvas, BASE_TOP);
730
731 canvas->SetFontAndSize("Helvetica", 8);
732
733 /* print title text */
734 int tmp_len;
735 if (fTitle != NULL) {
736 tmp_len = strlen(fTitle);
737
738 const int FIX_LEN = 20;
739 char *tmp_title = new char[tmp_len + FIX_LEN + 1];
740
741 try {
742 snprintf(tmp_title, tmp_len + FIX_LEN, "%d.%s ", fSection[0],
743 fTitle);
744
745 canvas->BeginText();
746 canvas->SetFontAndSize("Helvetica-Oblique", 8);
747 double tw = canvas->TextWidth(tmp_title);
748 canvas->MoveTextPos(BASE_RIGHT - tw - 5, BASE_TOP + 4);
749 canvas->ShowText(tmp_title);
750
751 canvas->EndText();
752 } catch (PdfException& e) {
753 fprintf(stderr, "%s\n", e.what());
754 }
755 delete[] tmp_title;
756 }
757
758 return;
759 }
760
761 const char*
GetStrParam(const char * str,char * param,int len)762 DocMaker::GetStrParam(const char* str, char* param, int len)
763 {
764 if (param == NULL)
765 return NULL;
766 *param = 0x00;
767
768 if (str == NULL)
769 return NULL;
770
771 const char* src = str;
772 char* dst = param;
773 bool intext = false;
774
775 for (int i = 0; i < len; src++){
776 if (*src == 0x00) {
777 *dst = *src;
778 return NULL;
779 } else if (*src == '"')
780 intext = !intext;
781 else if (!intext &&
782 (*src == ' ' || *src == 0x0d || *src == 0x0a || *src == 0x09)) {
783 if (dst != param) {
784 *dst = 0x00;
785 if (*src == 0x0d || *src == 0x0a)
786 return NULL;
787 else
788 return src++;
789 }
790 } else {
791 *dst++ = *src;
792 }
793 }
794
795 return NULL;
796 }
797
798 const char*
GetIntParam(const char * str,int * param)799 DocMaker::GetIntParam(const char* str, int* param)
800 {
801 char sparam[11];
802
803 str = GetStrParam(str, sparam, 11);
804 int i = atoi(sparam);
805 *param = i;
806
807 return str;
808 }
809
810 const char*
GetFloatParam(const char * str,double * param)811 DocMaker::GetFloatParam(const char* str, double* param)
812 {
813 char sparam[11];
814
815 str = GetStrParam(str, sparam, 11);
816 double f = atof(sparam);
817 *param = f;
818
819 return str;
820 }
821
822 void
SetDocName(const char * docname)823 DocMaker::SetDocName(const char* docname)
824 {
825 if (fDocName != NULL)
826 delete[] fDocName;
827
828 int len = strlen(docname) + 1;
829 fDocName = new char[len];
830 strcpy(fDocName, docname);
831 }
832
833 void
AddTitle(const char * buf)834 DocMaker::AddTitle(const char* buf)
835 {
836 char tmpbuf[255];
837
838 PDF_DEBUG_PRINT(("DocMaker::AddTitle(%s)\n", buf));
839 fFrontPage = fFrontPages->AddPage();
840 PdfContents* canvas = fFrontPage->Canvas();
841 canvas->AddFilter(PDF_FILTER_DEFLATE);
842
843 /* Print the document title. */
844 buf = GetStrParam(buf, tmpbuf, 255);
845 if (tmpbuf == NULL)
846 return;
847
848 SetDocName(tmpbuf);
849 canvas->BeginText();
850 canvas->SetFontAndSize("Helvetica-Bold", PDF_CHAR_SIZE_TITLE0);
851 canvas->MoveTextPos(75, 500);
852 int numchars = 0;
853 double width = canvas->TextWidth(tmpbuf, &numchars);
854 double tmpw = canvas->Width() - 75 * 2 - width;
855 canvas->SetCharSpace(tmpw / numchars);
856
857 canvas->ShowText(tmpbuf);
858 canvas->EndText();
859 canvas->SetCharSpace(0);
860
861 /* Print the subtitle. */
862 buf = GetStrParam(buf, tmpbuf, 255);
863 if (tmpbuf == NULL)
864 return;
865
866 canvas->BeginText();
867 canvas->SetFontAndSize("Helvetica-Bold", PDF_CHAR_SIZE_TITLE1);
868 width = canvas->TextWidth(tmpbuf, &numchars);
869 double tmpl = canvas->Width() - width - 80;
870 canvas->MoveTextPos(tmpl, 470);
871
872 canvas->ShowText(tmpbuf);
873 canvas->EndText();
874
875 /* Print the version NO. */
876 buf = GetStrParam(buf, tmpbuf, 255);
877 if (tmpbuf == NULL)
878 return;
879
880 canvas->BeginText();
881 canvas->SetFontAndSize("Helvetica-Bold", PDF_CHAR_SIZE_TITLE2);
882 width = canvas->TextWidth(tmpbuf, &numchars);
883
884 tmpl = canvas->Width() - width - 80;
885 canvas->MoveTextPos(tmpl, 100);
886
887 canvas->ShowText(tmpbuf);
888 canvas->EndText();
889
890 /* Print the copyright */
891 GetStrParam(buf, tmpbuf, 255);
892 if (tmpbuf == NULL)
893 return;
894
895 canvas->BeginText();
896 canvas->SetFontAndSize("Times-Bold", PDF_CHAR_SIZE_TITLE2);
897 width = canvas->TextWidth(tmpbuf, &numchars);
898 tmpl = canvas->Width() - width - 80;
899 canvas->MoveTextPos(tmpl, 80);
900
901 canvas->ShowText(tmpbuf);
902 canvas->EndText();
903
904 }
905
906 void
SetFont(const char * name)907 DocMaker::SetFont(const char* name)
908 {
909 double fsize = fCanvas->FontSize();
910 const char* fname = fCanvas->FontName();
911
912 if (strcmp(fname, name) != 0)
913 fCanvas->SetFontAndSize(name, fsize);
914 memset(fCurFont, 0x00, 64);
915 strncpy(fCurFont, name, 64 - 1);
916 }
917
918 void
SetIndent(int level)919 DocMaker::SetIndent(int level)
920 {
921 if (level == 0)
922 fLeftMargin = LEFT_MARGIN;
923 else
924 fLeftMargin += level * 10;
925 }
926
main(int argc,char ** argv)927 int main(int argc, char** argv)
928 {
929 FILE* infile;
930 const int BUF_LEN = 8192;
931 char buf[BUF_LEN];
932 char* filename = argv[1];
933 char* pdffname = argv[2];
934
935 if (argc < 3) {
936 fprintf(stderr, "usage: DocMaker input-file-name output-file-name.\n");
937 return -1;
938 }
939 infile = fopen(filename, "r");
940 if (infile == NULL) {
941 fprintf(stderr, "error: file open failed.\n");
942 return -1;
943 }
944
945 DocMaker* doc = NULL;
946 try {
947 doc = new DocMaker();
948 } catch (PdfException& e) {
949 fprintf(stderr, "%s\n", e.what());
950 fclose(infile);
951 return 1;
952 }
953
954 try {
955 while (fgets(buf, BUF_LEN, infile) != NULL) {
956 unsigned int len = strlen(buf);
957 if (buf[len - 1] == 0x0d || buf[len - 1] == 0x0a) {
958 buf[len - 1] = 0x00;
959 len--;
960 }
961 if (buf[len - 1] == 0x0d || buf[len - 1] == 0x0a) {
962 buf[len - 1] = 0x00;
963 len --;
964 }
965 doc->IncCurLine();
966
967 if (len >= 2) {
968
969 /* insert a brank line */
970 if (memcmp(buf, "%;", 2) == 0)
971 doc->ShowText("");
972 else
973
974 /* insert a brank line (harf)*/
975 if (memcmp(buf, "%:", 2) == 0)
976 doc->IncLine();
977 else
978
979 /* comment lines */
980 if (memcmp(buf, "%#", 2) == 0)
981 ;
982 else
983
984 /* add front page */
985 if (memcmp(buf, "%T", 2) == 0) {
986 char* pbuf = buf + 2;
987 doc->AddTitle(pbuf);
988 } else
989
990 /* add section. */
991 if (memcmp(buf, "%S", 2) == 0) {
992 int level;
993 char title[256];
994 const char* pbuf = buf + 2;
995
996 pbuf = doc->GetStrParam(pbuf, title, 256);
997 doc->GetIntParam(pbuf, &level);
998
999 try {
1000 doc->AddSection(title, level);
1001 } catch (PdfException& e) {
1002 fprintf(stderr, e.what());
1003 exit(2);
1004 }
1005 } else
1006
1007 /* show image. */
1008 if (memcmp(buf, "%I", 2) == 0) {
1009 char title[256];
1010 char filename[256];
1011 const char* pbuf = buf + 2;
1012
1013 pbuf = doc->GetStrParam(pbuf, title, 256);
1014 pbuf = doc->GetStrParam(pbuf, filename, 256);
1015
1016 int width = 0;
1017 int height = 0;
1018 if (pbuf != NULL)
1019 pbuf = doc->GetIntParam(pbuf, &width);
1020 if (pbuf != NULL)
1021 doc->GetIntParam(pbuf, &height);
1022
1023 doc->ShowImage(title, filename, width, height);
1024
1025 } else
1026
1027 /* insert figure */
1028 if (memcmp(buf, "%W", 2) == 0 && len > 8) {
1029 char title[256];
1030 char filename[256];
1031 double height;
1032 double width;
1033 const char* pbuf = buf + 2;
1034
1035 pbuf = doc->GetStrParam(pbuf, title, 256);
1036 pbuf = doc->GetStrParam(pbuf, filename, 256);
1037 pbuf = doc->GetFloatParam(pbuf, &width);
1038 pbuf = doc->GetFloatParam(pbuf, &height);
1039
1040 doc->ShowWMFImage(title, filename, width, height);
1041 } else
1042
1043 /* change default font */
1044
1045 if (memcmp(buf, "%C", 2) == 0) {
1046 char font_name[64];
1047 const char* pbuf = buf + 2;
1048
1049 doc->GetStrParam(pbuf, font_name, 64);
1050 doc->SetFont(font_name);
1051 } else
1052
1053 /* set indent */
1054 if (memcmp(buf, "%L", 2) == 0) {
1055 int indent;
1056 const char* pbuf = buf + 2;
1057
1058 doc->GetIntParam(pbuf, &indent);
1059 doc->SetIndent(indent);
1060 } else
1061
1062 /* label */
1063 if (memcmp(buf, "%A", 2) == 0) {
1064 int indent;
1065 char label[128];
1066 const char* pbuf = buf + 2;
1067
1068 pbuf = doc->GetIntParam(pbuf, &indent);
1069 doc->GetStrParam(pbuf, label, 128);
1070 doc->ShowLabel(label, indent);
1071 } else
1072
1073 /* print text */
1074 doc->ShowText(buf);
1075 }
1076 }
1077 doc->MakeIndex();
1078 doc->MakeOutline();
1079 doc->WriteToFile(pdffname);
1080 } catch (PdfException& e) {
1081 fprintf(stderr, "ERROR: %s line:%d.\n", e.what(), doc->CurLine());
1082 delete doc;
1083 fclose(infile);
1084 exit(1);
1085 }
1086
1087 fclose(infile);
1088
1089 delete doc;
1090 }
1091
1092