X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/halibut/blobdiff_plain/dd5670114aefff19fc0566af34a2c3f64ce1bb6b..60daa966e8090794ec307cddebf296f0cc0a3f20:/bk_paper.c diff --git a/bk_paper.c b/bk_paper.c index f6b18b8..aed648c 100644 --- a/bk_paper.c +++ b/bk_paper.c @@ -199,31 +199,31 @@ static paper_conf paper_configure(paragraph *source, font_list *fontlist) { /* * Defaults. */ - ret.paper_width = 595 * 4096; - ret.paper_height = 841 * 4096; - ret.left_margin = 72 * 4096; - ret.top_margin = 72 * 4096; - ret.right_margin = 72 * 4096; - ret.bottom_margin = 108 * 4096; - ret.indent_list_bullet = 6 * 4096; - ret.indent_list_after = 18 * 4096; - ret.indent_quote = 18 * 4096; - ret.base_leading = 4096; - ret.base_para_spacing = 10 * 4096; - ret.chapter_top_space = 72 * 4096; - ret.sect_num_left_space = 12 * 4096; - ret.chapter_underline_depth = 14 * 4096; - ret.chapter_underline_thickness = 3 * 4096; - ret.rule_thickness = 1 * 4096; + ret.paper_width = 595 * UNITS_PER_PT; + ret.paper_height = 841 * UNITS_PER_PT; + ret.left_margin = 72 * UNITS_PER_PT; + ret.top_margin = 72 * UNITS_PER_PT; + ret.right_margin = 72 * UNITS_PER_PT; + ret.bottom_margin = 108 * UNITS_PER_PT; + ret.indent_list_bullet = 6 * UNITS_PER_PT; + ret.indent_list_after = 18 * UNITS_PER_PT; + ret.indent_quote = 18 * UNITS_PER_PT; + ret.base_leading = UNITS_PER_PT; + ret.base_para_spacing = 10 * UNITS_PER_PT; + ret.chapter_top_space = 72 * UNITS_PER_PT; + ret.sect_num_left_space = 12 * UNITS_PER_PT; + ret.chapter_underline_depth = 14 * UNITS_PER_PT; + ret.chapter_underline_thickness = 3 * UNITS_PER_PT; + ret.rule_thickness = 1 * UNITS_PER_PT; ret.base_font_size = 12; - ret.contents_indent_step = 24 * 4096; - ret.contents_margin = 84 * 4096; - ret.leader_separation = 12 * 4096; - ret.index_gutter = 36 * 4096; + ret.contents_indent_step = 24 * UNITS_PER_PT; + ret.contents_margin = 84 * UNITS_PER_PT; + ret.leader_separation = 12 * UNITS_PER_PT; + ret.index_gutter = 36 * UNITS_PER_PT; ret.index_cols = 2; - ret.index_minsep = 18 * 4096; + ret.index_minsep = 18 * UNITS_PER_PT; ret.pagenum_fontsize = 12; - ret.footer_distance = 32 * 4096; + ret.footer_distance = 32 * UNITS_PER_PT; ret.lquote = L"\x2018\0\x2019\0'\0'\0\0"; ret.rquote = uadv(ret.lquote); ret.bullet = L"\x2022\0-\0\0"; @@ -257,70 +257,70 @@ static paper_conf paper_configure(paragraph *source, font_list *fontlist) { ret.bullet = uadv(p->keyword); } else if (!ustricmp(p->keyword, L"paper-page-width")) { ret.paper_width = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-page-height")) { ret.paper_height = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-left-margin")) { ret.left_margin = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-top-margin")) { ret.top_margin = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-right-margin")) { ret.right_margin = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-bottom-margin")) { ret.bottom_margin = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-list-indent")) { ret.indent_list_bullet = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-listitem-indent")) { ret.indent_list = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-quote-indent")) { ret.indent_quote = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-base-leading")) { ret.base_leading = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-base-para-spacing")) { ret.base_para_spacing = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-chapter-top-space")) { ret.chapter_top_space = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-sect-num-left-space")) { ret.sect_num_left_space = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-chapter-underline-depth")) { ret.chapter_underline_depth = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-chapter-underline-thickness")) { ret.chapter_underline_thickness = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-rule-thickness")) { ret.rule_thickness = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-contents-indent-step")) { ret.contents_indent_step = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-contents-margin")) { ret.contents_margin = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-leader-separation")) { ret.leader_separation = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-index-gutter")) { ret.index_gutter = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-index-minsep")) { ret.index_minsep = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-footer-distance")) { ret.footer_distance = - (int) 0.5 + 4096.0 * utof(uadv(p->keyword)); + (int) 0.5 + FUNITS_PER_PT * utof(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"paper-base-font-size")) { ret.base_font_size = utoi(uadv(p->keyword)); @@ -399,7 +399,7 @@ void *paper_pre_backend(paragraph *sourceform, keywordlist *keywords, paragraph index_placeholder_para; page_data *first_index_page; - fontlist = mknew(font_list); + fontlist = snew(font_list); fontlist->head = fontlist->tail = NULL; ourconf = paper_configure(sourceform, fontlist); @@ -416,7 +416,7 @@ void *paper_pre_backend(paragraph *sourceform, keywordlist *keywords, has_index = FALSE; for (i = 0; (entry = index234(idx->entries, i)) != NULL; i++) { - paper_idx *pi = mknew(paper_idx); + paper_idx *pi = snew(paper_idx); has_index = TRUE; @@ -682,7 +682,7 @@ void *paper_pre_backend(paragraph *sourceform, keywordlist *keywords, } if (has_index) { - first_index_page = mknew(page_data); + first_index_page = snew(page_data); first_index_page->next = first_index_page->prev = NULL; first_index_page->first_line = NULL; first_index_page->last_line = NULL; @@ -910,7 +910,7 @@ void *paper_pre_backend(paragraph *sourceform, keywordlist *keywords, * Start putting together the overall document structure we're * going to return. */ - doc = mknew(document); + doc = snew(document); doc->fonts = fontlist; doc->pages = pages; doc->paper_width = conf->paper_width; @@ -925,7 +925,7 @@ void *paper_pre_backend(paragraph *sourceform, keywordlist *keywords, { int osize = 20; - doc->outline_elements = mknewa(outline_element, osize); + doc->outline_elements = snewn(osize, outline_element); doc->n_outline_elements = 0; /* First find the title. */ @@ -944,7 +944,7 @@ void *paper_pre_backend(paragraph *sourceform, keywordlist *keywords, if (doc->n_outline_elements >= osize) { osize += 20; doc->outline_elements = - resize(doc->outline_elements, osize); + sresize(doc->outline_elements, osize, outline_element); } doc->outline_elements[doc->n_outline_elements].level = @@ -967,7 +967,7 @@ static para_data *make_para_data(int ptype, int paux, int indent, int rmargin, int extra_indent, firstline_indent, aux_indent; word *aux, *aux2; - pdata = mknew(para_data); + pdata = snew(para_data); pdata->outline_level = -1; pdata->outline_title = NULL; pdata->rect_type = RECT_NONE; @@ -1227,7 +1227,7 @@ static font_encoding *new_font_encoding(font_data *font) font_encoding *fe; int i; - fe = mknew(font_encoding); + fe = snew(font_encoding); fe->next = NULL; if (font->list->tail) @@ -1248,28 +1248,49 @@ static font_encoding *new_font_encoding(font_data *font) return fe; } +static int kern_cmp(void *a, void *b) +{ + kern_pair const *ka = a, *kb = b; + + if (ka->left < kb->left) + return -1; + if (ka->left > kb->left) + return 1; + if (ka->right < kb->right) + return -1; + if (ka->right > kb->right) + return 1; + return 0; +} + static font_data *make_std_font(font_list *fontlist, char const *name) { const int *widths; + const kern_pair *kerns; int nglyphs; font_data *f; font_encoding *fe; int i; + /* XXXKERN */ widths = ps_std_font_widths(name); - if (!widths) + kerns = ps_std_font_kerns(name); + if (!widths || !kerns) return NULL; for (nglyphs = 0; ps_std_glyphs[nglyphs] != NULL; nglyphs++); - f = mknew(font_data); + f = snew(font_data); f->list = fontlist; f->name = name; f->nglyphs = nglyphs; f->glyphs = ps_std_glyphs; f->widths = widths; - f->subfont_map = mknewa(subfont_map_entry, nglyphs); + f->kerns = newtree234(kern_cmp); + for (;kerns->left != 0xFFFF; kerns++) + add234(f->kerns, (void *)kerns); + f->subfont_map = snewn(nglyphs, subfont_map_entry); /* * Our first subfont will contain all of US-ASCII. This isn't @@ -1308,23 +1329,42 @@ static font_data *make_std_font(font_list *fontlist, char const *name) return f; } +/* NB: arguments are glyph numbers from font->bmp. */ +static int find_kern(font_data *font, int lindex, int rindex) +{ + kern_pair wantkp; + kern_pair const *kp; + + if (lindex == 0xFFFF || rindex == 0xFFFF) + return 0; + wantkp.left = lindex; + wantkp.right = rindex; + kp = find234(font->kerns, &wantkp, NULL); + if (kp == NULL) + return 0; + return kp->kern; +} + static int string_width(font_data *font, wchar_t const *string, int *errs) { int width = 0; + int index, oindex; if (errs) *errs = 0; + oindex = 0xFFFF; for (; *string; string++) { - int index; + index = (*string < 0 || *string > 0xFFFF ? 0xFFFF : + font->bmp[*string]); - index = font->bmp[(unsigned short)*string]; if (index == 0xFFFF) { if (errs) *errs = 1; } else { - width += font->widths[index]; + width += find_kern(font, oindex, index) + font->widths[index]; } + oindex = index; } return width; @@ -1431,7 +1471,7 @@ static void wrap_paragraph(para_data *pdata, word *words, for (i = 0; i < NFONTS; i++) if (line_height < pdata->sizes[i]) line_height = pdata->sizes[i]; - line_height *= 4096; + line_height *= UNITS_PER_PT; } spacewidth = (pdata->sizes[FONT_NORMAL] * @@ -1442,7 +1482,7 @@ static void wrap_paragraph(para_data *pdata, word *words, * comes up, but I'll make a random guess anyway and set my * space width to half the point size. */ - spacewidth = pdata->sizes[FONT_NORMAL] * 4096 / 2; + spacewidth = pdata->sizes[FONT_NORMAL] * UNITS_PER_PT / 2; } /* @@ -1466,7 +1506,7 @@ static void wrap_paragraph(para_data *pdata, word *words, word *wd; int len, wid, spaces; - ldata = mknew(line_data); + ldata = snew(line_data); ldata->pdata = pdata; ldata->first = p->begin; @@ -1546,11 +1586,11 @@ static page_data *page_breaks(line_data *first, line_data *last, */ for (l = last; l; l = l->prev) { - l->bestcost = mknewa(int, ncols+1); - l->vshortfall = mknewa(int, ncols+1); - l->text = mknewa(int, ncols+1); - l->space = mknewa(int, ncols+1); - l->page_last = mknewa(line_data *, ncols+1); + l->bestcost = snewn(ncols+1, int); + l->vshortfall = snewn(ncols+1, int); + l->text = snewn(ncols+1, int); + l->space = snewn(ncols+1, int); + l->page_last = snewn(ncols+1, line_data *); for (n = 0; n <= ncols; n++) { int minheight, text = 0, space = 0; @@ -1602,7 +1642,8 @@ static page_data *page_breaks(line_data *first, line_data *last, */ if (m != last && m->next && !m->next->page_break) { - int x = this_height - minheight; + int x = (this_height - minheight) / FUNITS_PER_PT * + 4096.0; int xf; xf = x & 0xFF; @@ -1654,7 +1695,7 @@ static page_data *page_breaks(line_data *first, line_data *last, page_data *page; int text, space, head; - page = mknew(page_data); + page = snew(page_data); page->next = NULL; page->prev = pt; if (pt) @@ -1691,9 +1732,11 @@ static page_data *page_breaks(line_data *first, line_data *last, text += l->line_height; l->page = page; - l->ypos = text + space + head + - space * (float)page->first_line->vshortfall[n] / - page->first_line->space[n]; + l->ypos = text + space + head; + if (page->first_line->space[n]) { + l->ypos += space * (float)page->first_line->vshortfall[n] / + page->first_line->space[n]; + } if (l == page->last_line) break; @@ -1712,7 +1755,7 @@ static page_data *page_breaks(line_data *first, line_data *last, static void add_rect_to_page(page_data *page, int x, int y, int w, int h) { - rect *r = mknew(rect); + rect *r = snew(rect); r->next = NULL; if (page->last_rect) @@ -1733,7 +1776,7 @@ static void add_string_to_page(page_data *page, int x, int y, { text_fragment *frag; - frag = mknew(text_fragment); + frag = snew(text_fragment); frag->next = NULL; if (page->last_text) @@ -1757,14 +1800,17 @@ static int render_string(page_data *page, font_data *font, int fontsize, int x, int y, wchar_t *str) { char *text; - int textpos, textwid, glyph; + int textpos, textwid, kern, glyph, oglyph; font_encoding *subfont = NULL, *sf; - text = mknewa(char, 1 + ustrlen(str)); + text = snewn(1 + ustrlen(str), char); textpos = textwid = 0; + glyph = 0xFFFF; while (*str) { - glyph = font->bmp[*str]; + oglyph = glyph; + glyph = (*str < 0 || *str > 0xFFFF ? 0xFFFF : + font->bmp[*str]); if (glyph == 0xFFFF) { str++; @@ -1798,16 +1844,19 @@ static int render_string(page_data *page, font_data *font, int fontsize, sf = font->latest_subfont; } - if (!subfont || sf != subfont) { + kern = find_kern(font, oglyph, glyph) * fontsize; + + if (!subfont || sf != subfont || kern) { if (subfont) { text[textpos] = '\0'; add_string_to_page(page, x, y, subfont, fontsize, text, textwid); - x += textwid; + x += textwid + kern; } else { assert(textpos == 0); } textpos = 0; + textwid = 0; subfont = sf; } @@ -1876,7 +1925,7 @@ static int render_text(page_data *page, para_data *pdata, line_data *ldata, } } if (dest.type != NONE) { - *xr = mknew(xref); + *xr = snew(xref); (*xr)->dest = dest; /* structure copy */ if (page->last_xref) page->last_xref->next = *xr; @@ -2036,7 +2085,7 @@ static int render_line(line_data *ldata, int left_x, int top_y, * previous line. */ if (dest->type != NONE) { - xr = mknew(xref); + xr = snew(xref); xr->next = NULL; xr->dest = *dest; /* structure copy */ if (ldata->page->last_xref) @@ -2118,7 +2167,7 @@ static void render_para(para_data *pdata, paper_conf *conf, */ if (pdata->contents_entry && ldata->page != cxref_page) { cxref_page = ldata->page; - cxref = mknew(xref); + cxref = snew(xref); cxref->next = NULL; cxref->dest.type = PAGE; if (pdata->contents_entry == index_placeholder) { @@ -2222,7 +2271,7 @@ static void render_para(para_data *pdata, paper_conf *conf, static para_data *code_paragraph(int indent, word *words, paper_conf *conf) { - para_data *pdata = mknew(para_data); + para_data *pdata = snew(para_data); /* * For code paragraphs, I'm going to hack grievously and @@ -2284,12 +2333,12 @@ static para_data *code_paragraph(int indent, word *words, paper_conf *conf) * which has the same emphasis. Form it into a word * structure. */ - w = mknew(word); + w = snew(word); w->next = NULL; w->alt = NULL; w->type = (prev == 0 ? word_WeakCode : prev == 1 ? word_Emph : word_Normal); - w->text = mknewa(wchar_t, t-start+1); + w->text = snewn(t-start+1, wchar_t); memcpy(w->text, start, (t-start) * sizeof(wchar_t)); w->text[t-start] = '\0'; w->breaks = FALSE; @@ -2304,12 +2353,12 @@ static para_data *code_paragraph(int indent, word *words, paper_conf *conf) prev = -1; } - ldata = mknew(line_data); + ldata = snew(line_data); ldata->pdata = pdata; ldata->first = lhead; ldata->end = NULL; - ldata->line_height = conf->base_font_size * 4096; + ldata->line_height = conf->base_font_size * UNITS_PER_PT; ldata->xpos = indent; @@ -2339,10 +2388,10 @@ static para_data *code_paragraph(int indent, word *words, paper_conf *conf) static para_data *rule_paragraph(int indent, paper_conf *conf) { - para_data *pdata = mknew(para_data); + para_data *pdata = snew(para_data); line_data *ldata; - ldata = mknew(line_data); + ldata = snew(line_data); ldata->pdata = pdata; ldata->first = NULL; @@ -2448,7 +2497,7 @@ static wchar_t *prepare_outline_title(word *first, wchar_t *separator, static word *fake_word(wchar_t *text) { - word *ret = mknew(word); + word *ret = snew(word); ret->next = NULL; ret->alt = NULL; ret->type = word_Normal; @@ -2460,7 +2509,7 @@ static word *fake_word(wchar_t *text) static word *fake_space_word(void) { - word *ret = mknew(word); + word *ret = snew(word); ret->next = NULL; ret->alt = NULL; ret->type = word_WhiteSpace; @@ -2472,7 +2521,7 @@ static word *fake_space_word(void) static word *fake_page_ref(page_data *page) { - word *ret = mknew(word); + word *ret = snew(word); ret->next = NULL; ret->alt = NULL; ret->type = word_PageXref; @@ -2485,7 +2534,7 @@ static word *fake_page_ref(page_data *page) static word *fake_end_ref(void) { - word *ret = mknew(word); + word *ret = snew(word); ret->next = NULL; ret->alt = NULL; ret->type = word_XrefEnd;