/*
* 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";
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));
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);
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;
}
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;
* 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;
{
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. */
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 =
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;
font_encoding *fe;
int i;
- fe = mknew(font_encoding);
+ fe = snew(font_encoding);
fe->next = NULL;
if (font->list->tail)
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
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;
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] *
* 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;
}
/*
word *wd;
int len, wid, spaces;
- ldata = mknew(line_data);
+ ldata = snew(line_data);
ldata->pdata = pdata;
ldata->first = p->begin;
*/
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;
*/
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;
page_data *page;
int text, space, head;
- page = mknew(page_data);
+ page = snew(page_data);
page->next = NULL;
page->prev = pt;
if (pt)
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;
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)
{
text_fragment *frag;
- frag = mknew(text_fragment);
+ frag = snew(text_fragment);
frag->next = NULL;
if (page->last_text)
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++;
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;
}
}
}
if (dest.type != NONE) {
- *xr = mknew(xref);
+ *xr = snew(xref);
(*xr)->dest = dest; /* structure copy */
if (page->last_xref)
page->last_xref->next = *xr;
* 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)
*/
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) {
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
* 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;
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;
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;
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;
static word *fake_space_word(void)
{
- word *ret = mknew(word);
+ word *ret = snew(word);
ret->next = NULL;
ret->alt = NULL;
ret->type = word_WhiteSpace;
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;
static word *fake_end_ref(void)
{
- word *ret = mknew(word);
+ word *ret = snew(word);
ret->next = NULL;
ret->alt = NULL;
ret->type = word_XrefEnd;