Support for emitting outlines using pdfmark.
authorben <ben@cda61777-01e9-0310-a592-d414129be87e>
Sat, 2 Dec 2006 16:33:22 +0000 (16:33 +0000)
committerben <ben@cda61777-01e9-0310-a592-d414129be87e>
Sat, 2 Dec 2006 16:33:22 +0000 (16:33 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/halibut@6952 cda61777-01e9-0310-a592-d414129be87e

bk_pdf.c
bk_ps.c
paper.h

index 8b03ae2..ba19372 100644 (file)
--- a/bk_pdf.c
+++ b/bk_pdf.c
@@ -40,7 +40,6 @@ static void pdf_string_len(void (*add)(object *, char const *),
                           object *, char const *, int);
 static void objref(object *o, object *dest);
 static void objdest(object *o, page_data *p);
-static char *pdf_outline_convert(wchar_t *s, int *len);
 
 static int is_std_font(char const *name);
 
@@ -725,7 +724,7 @@ static void make_pages_node(object *node, object *parent, page_data *first,
  * encodes in either PDFDocEncoding (a custom superset of
  * ISO-8859-1) or UTF-16BE.
  */
-static char *pdf_outline_convert(wchar_t *s, int *len) {
+char *pdf_outline_convert(wchar_t *s, int *len) {
     char *ret;
 
     ret = utoa_careful_dup(s, CS_PDF);
diff --git a/bk_ps.c b/bk_ps.c
index 86b8465..35fe582 100644 (file)
--- a/bk_ps.c
+++ b/bk_ps.c
@@ -7,6 +7,7 @@
 #include "paper.h"
 
 static void ps_comment(FILE *fp, char const *leader, word *words);
+static void ps_string_len(FILE *fp, char const *str, int len);
 static void ps_string(FILE *fp, char const *str);
 
 paragraph *ps_config_filename(char *filename)
@@ -24,6 +25,9 @@ void ps_backend(paragraph *sourceform, keywordlist *keywords,
     FILE *fp;
     char *filename;
     paragraph *p;
+    outline_element *oe;
+    int noe;
+
 
     IGNORE(keywords);
     IGNORE(idx);
@@ -119,6 +123,18 @@ void ps_backend(paragraph *sourceform, keywordlist *keywords,
     fprintf(fp, "%%%%BeginSetup\n");
 
     /*
+     * Assign a destination name to each page for pdfmark purposes.
+     */
+    pageno = 0;
+    for (page = doc->pages; page; page = page->next) {
+       char *buf;
+       pageno++;
+       buf = snewn(12, char);
+       sprintf(buf, "/p%d", pageno);
+       page->spare = buf;
+    }
+
+    /*
      * This is as good a place as any to put version IDs.
      */
     for (p = sourceform; p; p = p->next)
@@ -137,11 +153,29 @@ void ps_backend(paragraph *sourceform, keywordlist *keywords,
            doc->paper_height / FUNITS_PER_PT);
     fprintf(fp, "} if\n");
 
-    /* Request outline view if the document is converted to PDF. */
-    fprintf(fp,
-           "/pdfmark where {\n"
-           "  pop [ /PageMode /UseOutlines /DOCVIEW pdfmark\n"
-           "} if\n");
+    /* Outline etc, only if pdfmark is supported */
+    fprintf(fp, "/pdfmark where { pop %% if\n");
+    fprintf(fp, "  [/PageMode/UseOutlines/DOCVIEW pdfmark\n");
+    noe = doc->n_outline_elements;
+    for (oe = doc->outline_elements; noe; oe++, noe--) {
+       char *title;
+       int titlelen, count, i;
+
+       title = pdf_outline_convert(oe->pdata->outline_title, &titlelen);
+
+       count = 0;
+       for (i = 1; i < noe && oe[i].level > oe->level; i++)
+           if (oe[i].level == oe->level + 1)
+               count++;
+       if (oe->level > 0) count = -count;
+
+       fprintf(fp, "  [/Title");
+       ps_string_len(fp, title, titlelen);
+       sfree(title);
+       fprintf(fp, "/Dest%s/Count %d/OUT pdfmark\n",
+               (char *)oe->pdata->first->page->spare, count);
+    }
+    fprintf(fp, "} if\n");
 
     for (fe = doc->fonts->head; fe; fe = fe->next) {
        /* XXX This may request the same font multiple times. */
@@ -187,18 +221,6 @@ void ps_backend(paragraph *sourceform, keywordlist *keywords,
     fprintf(fp, "%%%%EndSetup\n");
 
     /*
-     * Assign a destination name to each page for pdfmark purposes.
-     */
-    pageno = 0;
-    for (page = doc->pages; page; page = page->next) {
-       char *buf;
-       pageno++;
-       buf = snewn(12, char);
-       sprintf(buf, "/p%d", pageno);
-       page->spare = buf;
-    }
-
-    /*
      * Output the text and graphics.
      */
     pageno = 0;
@@ -310,18 +332,39 @@ static void ps_comment(FILE *fp, char const *leader, word *words)
     fprintf(fp, "\n");
 }
 
-static void ps_string(FILE *fp, char const *str) {
+static void ps_string_len(FILE *fp, char const *str, int len) {
     char const *c;
-
-    fprintf(fp, "(");
-    for (c = str; *c; c++) {
-       if (*c < ' ' || *c > '~') {
-           fprintf(fp, "\\%03o", 0xFF & (int)*c);
-       } else {
-           if (*c == '(' || *c == ')' || *c == '\\')
-               fputc('\\', fp);
-           fputc(*c, fp);
+    int score = 0;
+
+    for (c = str; c < str+len; c++) {
+       if (*c < ' ' || *c > '~')
+           score += 2;
+       else if (*c == '(' || *c == ')' || *c == '\\')
+           score += 0;
+       else
+           score -= 1;
+    }
+    if (score > 0) {
+       fprintf(fp, "<");
+       for (c = str; c < str+len; c++) {
+           fprintf(fp, "%02X", 0xFF & (int)*c);
        }
+       fprintf(fp, ">");
+    } else {
+       fprintf(fp, "(");
+       for (c = str; c < str+len; c++) {
+           if (*c < ' ' || *c > '~') {
+               fprintf(fp, "\\%03o", 0xFF & (int)*c);
+           } else {
+               if (*c == '(' || *c == ')' || *c == '\\')
+                   fputc('\\', fp);
+               fputc(*c, fp);
+           }
+       }
+       fprintf(fp, ")");
     }
-    fprintf(fp, ")");
+}
+
+static void ps_string(FILE *fp, char const *str) {
+    ps_string_len(fp, str, strlen(str));
 }
diff --git a/paper.h b/paper.h
index 2811f37..03b0f1b 100644 (file)
--- a/paper.h
+++ b/paper.h
@@ -371,4 +371,9 @@ void init_std_fonts(void);
 const int *ps_std_font_widths(char const *fontname);
 const kern_pair *ps_std_font_kerns(char const *fontname);
 
+/*
+ * Function from bk_pdf.c borrowed by bk_ps.c
+ */
+char *pdf_outline_convert(wchar_t *s, int *len);
+
 #endif