X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/halibut/blobdiff_plain/416dfe1719254d4718888fdbb0b0ac6d3ad91705..60daa966e8090794ec307cddebf296f0cc0a3f20:/bk_paper.c diff --git a/bk_paper.c b/bk_paper.c index a8479c7..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)); @@ -1248,16 +1248,34 @@ 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++); @@ -1269,6 +1287,9 @@ static font_data *make_std_font(font_list *fontlist, char const *name) f->nglyphs = nglyphs; f->glyphs = ps_std_glyphs; f->widths = widths; + f->kerns = newtree234(kern_cmp); + for (;kerns->left != 0xFFFF; kerns++) + add234(f->kerns, (void *)kerns); f->subfont_map = snewn(nglyphs, subfont_map_entry); /* @@ -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; } /* @@ -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; @@ -1759,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 = 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++; @@ -1800,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; } @@ -2311,7 +2358,7 @@ static para_data *code_paragraph(int indent, word *words, paper_conf *conf) 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;