X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/halibut/blobdiff_plain/3f3d1accc32d4228ee695072994dba0a76b905b9..5b1d0032b0eb6f4a347c0c2cfdbe6e4bb4f959ab:/bk_paper.c?ds=sidebyside diff --git a/bk_paper.c b/bk_paper.c index e993ece..a9f6f24 100644 --- a/bk_paper.c +++ b/bk_paper.c @@ -10,25 +10,71 @@ */ /* - * To be done: - * - * - header/footer? Page numbers at least would be handy. Fully - * configurable footer can wait, though. - * - * That should bring us to the same level of functionality that - * original-Halibut had, and the same in PDF plus the obvious - * interactive navigation features. After that, in future work: + * TODO in future work: * * - linearised PDF, perhaps? * + * - we should use PDFDocEncoding or Unicode for outline strings, + * now that I actually know how to do them. Probably easiest if + * I do this _after_ bringing in libcharset, since I can simply + * supply PDFDocEncoding in there. + * * - I'm uncertain of whether I need to include a ToUnicode CMap * in each of my font definitions in PDF. Currently things (by * which I mean cut and paste out of acroread) seem to be * working fairly happily without it, but I don't know. * + * - rather than the ugly aux_text mechanism for rendering chapter + * titles, we could actually build the correct word list and + * wrap it as a whole. + * + * - get vertical font metrics and use them to position the PDF + * xref boxes more pleasantly + * * - configurability + * * all the measurements in `conf' should be configurable + * + notably paper size/shape + * * page header and footer should be configurable; we should + * be able to shift the page number elsewhere, and add other + * things such as the current chapter/section title and fixed + * text + * * remove the fixed mapping from heading levels to heading + * styles; offer a menu of styles from which the user can + * choose at every heading level + * * first-line indent in paragraphs + * * fixed text: `Contents', `Index', bullet, quotes, the + * colon-space and full stop in chapter title constructions + * * configurable location of contents? + * * certainly configurably _remove_ the contents, and possibly + * also the index + * * double-sided document switch? + * + means you have two header/footer formats which + * alternate + * + and means that mandatory page breaks before chapter + * titles should include a blank page if necessary to + * start the next section to a right-hand page * * - title pages + * + * - ability to import other Type 1 fonts + * * we need to parse the font to extract its metrics + * * then we pass the font bodily to both PS and PDF so it can + * be included in the output file + * + * - character substitution for better typography? + * * fi, fl, ffi, ffl ligatures + * * use real ellipsis rather than ... + * * a hyphen in a word by itself might prefer to be an en-dash + * * (Americans might even want a convenient way to use an + * em-dash) + * * DON'T DO ANY OF THE ABOVE WITHIN \c OR \cw! + * * substituting `minus' for `hyphen' in the standard encoding + * is probably preferable in Courier, though certainly not in + * the main text font + * * if I do do this lot, I'm rather inclined to at least try + * to think up a configurable way to do it so that Americans + * can do em-dash tricks without my intervention and other + * people can do other odd things too. */ #include @@ -64,6 +110,8 @@ struct paper_conf_Tag { int index_gutter; int index_cols; int index_minsep; + int pagenum_fontsize; + int footer_distance; /* These are derived from the above */ int base_width; int page_height; @@ -103,6 +151,7 @@ static int render_line(line_data *ldata, int left_x, int top_y, static void render_para(para_data *pdata, paper_conf *conf, keywordlist *keywords, indexdata *idx, paragraph *index_placeholder, page_data *index_page); +static int string_width(font_data *font, wchar_t const *string, int *errs); static int paper_width_simple(para_data *pdata, word *text); static para_data *code_paragraph(int indent, word *words, paper_conf *conf); static para_data *rule_paragraph(int indent, paper_conf *conf); @@ -164,6 +213,8 @@ void *paper_pre_backend(paragraph *sourceform, keywordlist *keywords, conf->index_gutter = 36 * 4096; conf->index_cols = 2; conf->index_minsep = 18 * 4096; + conf->pagenum_fontsize = 12; + conf->footer_distance = 32 * 4096; conf->base_width = conf->paper_width - conf->left_margin - conf->right_margin; @@ -173,8 +224,6 @@ void *paper_pre_backend(paragraph *sourceform, keywordlist *keywords, (conf->base_width - (conf->index_cols-1) * conf->index_gutter) / conf->index_cols; - IGNORE(idx); /* FIXME */ - /* * First, set up some font structures. */ @@ -461,7 +510,7 @@ void *paper_pre_backend(paragraph *sourceform, keywordlist *keywords, for (page = pages; page; page = page->next) { sprintf(buf, "%d", ++pagenum); - page->number = ufroma_dup(buf); + page->number = ufroma_dup(buf, CS_ASCII); } if (has_index) { @@ -475,7 +524,7 @@ void *paper_pre_backend(paragraph *sourceform, keywordlist *keywords, /* And don't forget the as-yet-uncreated index. */ sprintf(buf, "%d", ++pagenum); - first_index_page->number = ufroma_dup(buf); + first_index_page->number = ufroma_dup(buf, CS_ASCII); } } @@ -515,6 +564,9 @@ void *paper_pre_backend(paragraph *sourceform, keywordlist *keywords, paper_idx *pi = (paper_idx *)entry->backend_data; para_data *text, *pages; + if (!pi->words) + continue; + text = make_para_data(para_Normal, 0, 0, conf->base_width - conf->index_colwidth, NULL, NULL, entry->text, conf); @@ -631,7 +683,7 @@ void *paper_pre_backend(paragraph *sourceform, keywordlist *keywords, for (page = ipages->next; page; page = page->next) { char buf[40]; sprintf(buf, "%d", ++pagenum); - page->number = ufroma_dup(buf); + page->number = ufroma_dup(buf, CS_ASCII); } /* @@ -664,6 +716,29 @@ void *paper_pre_backend(paragraph *sourceform, keywordlist *keywords, } /* + * Draw the headers and footers. + * + * FIXME: this should be fully configurable, but for the moment + * I'm just going to put in page numbers in the centre of a + * footer and leave it at that. + */ + { + page_data *page; + + for (page = pages; page; page = page->next) { + int width; + + width = conf->pagenum_fontsize * + string_width(conf->tr, page->number, NULL); + + render_string(page, conf->tr, conf->pagenum_fontsize, + conf->left_margin + (conf->base_width - width)/2, + conf->bottom_margin - conf->footer_distance, + page->number); + } + } + + /* * Start putting together the overall document structure we're * going to return. */ @@ -1485,7 +1560,8 @@ static void add_rect_to_page(page_data *page, int x, int y, int w, int h) } static void add_string_to_page(page_data *page, int x, int y, - font_encoding *fe, int size, char *text) + font_encoding *fe, int size, char *text, + int width) { text_fragment *frag; @@ -1503,6 +1579,7 @@ static void add_string_to_page(page_data *page, int x, int y, frag->fe = fe; frag->fontsize = size; frag->text = dupstr(text); + frag->width = width; } /* @@ -1521,8 +1598,10 @@ static int render_string(page_data *page, font_data *font, int fontsize, while (*str) { glyph = font->bmp[*str]; - if (glyph == 0xFFFF) + if (glyph == 0xFFFF) { + str++; continue; /* nothing more we can do here */ + } /* * Find which subfont this character is going in. @@ -1554,7 +1633,8 @@ static int render_string(page_data *page, font_data *font, int fontsize, if (!subfont || sf != subfont) { if (subfont) { text[textpos] = '\0'; - add_string_to_page(page, x, y, subfont, fontsize, text); + add_string_to_page(page, x, y, subfont, fontsize, text, + textwid); x += textwid; } else { assert(textpos == 0); @@ -1571,7 +1651,7 @@ static int render_string(page_data *page, font_data *font, int fontsize, if (textpos > 0) { text[textpos] = '\0'; - add_string_to_page(page, x, y, subfont, fontsize, text); + add_string_to_page(page, x, y, subfont, fontsize, text, textwid); x += textwid; } @@ -1602,7 +1682,7 @@ static int render_text(page_data *page, para_data *pdata, line_data *ldata, if (text->type == word_HyperLink) { dest.type = URL; - dest.url = utoa_dup(text->text); + dest.url = utoa_dup(text->text, CS_ASCII); dest.page = NULL; } else if (text->type == word_PageXref) { dest.type = PAGE; @@ -1663,7 +1743,10 @@ static int render_text(page_data *page, para_data *pdata, line_data *ldata, * referenced by an index entry. */ case word_IndexRef: - { + /* + * We don't create index references in contents entries. + */ + if (!pdata->contents_entry) { indextag *tag; int i; @@ -1921,13 +2004,6 @@ static void render_para(para_data *pdata, paper_conf *conf, wid = paper_width_simple(pdata, w); sfree(w); - render_string(pdata->last->page, - pdata->fonts[FONT_NORMAL], - pdata->sizes[FONT_NORMAL], - conf->paper_width - conf->right_margin - wid, - (conf->paper_height - conf->top_margin - - pdata->last->ypos), num); - for (x = 0; x < conf->base_width; x += conf->leader_separation) if (x - conf->leader_separation > last_x - conf->left_margin && x + conf->leader_separation < conf->base_width - wid) @@ -1937,6 +2013,13 @@ static void render_para(para_data *pdata, paper_conf *conf, conf->left_margin + x, (conf->paper_height - conf->top_margin - pdata->last->ypos), L"."); + + render_string(pdata->last->page, + pdata->fonts[FONT_NORMAL], + pdata->sizes[FONT_NORMAL], + conf->paper_width - conf->right_margin - wid, + (conf->paper_height - conf->top_margin - + pdata->last->ypos), num); } /*