diff options
author | Taco Hoekwater <taco@elvenkind.com> | 2009-03-27 15:30:55 +0000 |
---|---|---|
committer | Taco Hoekwater <taco@elvenkind.com> | 2009-03-27 15:30:55 +0000 |
commit | 178de0871d690556af74f3768c11bc812b07f347 (patch) | |
tree | a939c31adc90d6207848effaec87dd78ec00e658 /Build/source/texk/web2c/luatexdir/pdf | |
parent | 4865b23b5199697829e4e6633f2f697b4634c462 (diff) |
Import of luatex 0.37.0 (autoreconf has not been run yet!)
git-svn-id: svn://tug.org/texlive/trunk@12529 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/pdf')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/pdf/pagetree.c | 268 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/pdf/pdfpage.c | 565 |
2 files changed, 833 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/pdf/pagetree.c b/Build/source/texk/web2c/luatexdir/pdf/pagetree.c new file mode 100644 index 00000000000..d88bdea51e8 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/pdf/pagetree.c @@ -0,0 +1,268 @@ +/* pagetree.c + + Copyright 2006-2009 Taco Hoekwater <taco@luatex.org> + + This file is part of LuaTeX. + + LuaTeX is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + LuaTeX is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU General Public License along + with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ + +/* $Id: pagetree.c 2031 2009-03-16 10:30:47Z taco $ */ + +#include "ptexlib.h" + +#include "openbsd-compat.h" +#ifdef HAVE_ASPRINTF /* asprintf is not defined in openbsd-compat.h, but in stdio.h */ +# include <stdio.h> +#endif + +#include "sys/types.h" +#ifndef __MINGW32__ +# include "sysexits.h" +#else +# define EX_SOFTWARE 70 +#endif + +static const char __svn_version[] = "$Id: pagetree.c 2031 2009-03-16 10:30:47Z taco $ $URL: http://scm.foundry.supelec.fr/svn/luatex/trunk/src/texk/web2c/luatexdir/pdf/pagetree.c $"; + +/**********************************************************************/ +/* Page diversions */ + +#ifdef DEBUG +# define PAGES_TREE_KIDSMAX 3 +#else +# define PAGES_TREE_KIDSMAX 6 +#endif + +static struct avl_table *divert_list_tree = NULL; + +typedef struct pages_entry_ { + integer objnum; /* object number of this /Pages object */ + integer number_of_pages; /* total number of all pages below */ + integer number_of_kids; /* number of direct kid objects */ + integer kids[PAGES_TREE_KIDSMAX]; /* array of kid object numbers */ + struct pages_entry_ *next; +} pages_entry; + +typedef struct divert_list_entry_ { + integer divnum; + pages_entry *first; + pages_entry *last; +} divert_list_entry; + +static int comp_divert_list_entry(const void *pa, const void *pb, void *p) +{ + if (((const divert_list_entry *) pa)->divnum > + ((const divert_list_entry *) pb)->divnum) + return 1; + if (((const divert_list_entry *) pa)->divnum < + ((const divert_list_entry *) pb)->divnum) + return -1; + return 0; +} + +static pages_entry *new_pages_entry() +{ + pages_entry *p; + int i; + p = xtalloc(1, pages_entry); + p->number_of_pages = p->number_of_kids = 0; + for (i = 0; i < PAGES_TREE_KIDSMAX; i++) + p->kids[i] = 0; + p->next = NULL; + pdf_create_obj(0, 0); + p->objnum = obj_ptr; + return p; +} + +static divert_list_entry *new_divert_list_entry() +{ + divert_list_entry *d; + d = xtalloc(1, divert_list_entry); + d->first = d->last = NULL; + return d; +} + +static void ensure_list_tree() +{ + if (divert_list_tree == NULL) { + divert_list_tree = + avl_create(comp_divert_list_entry, NULL, &avl_xallocator); + assert(divert_list_tree != NULL); + } +} + +static divert_list_entry *get_divert_list(integer divnum) +{ + divert_list_entry *d, tmp; + void **aa; + tmp.divnum = divnum; + d = (divert_list_entry *) avl_find(divert_list_tree, &tmp); + if (d == NULL) { + d = new_divert_list_entry(); + d->divnum = divnum; + aa = avl_probe(divert_list_tree, d); + assert(aa != NULL); + } + return d; +} + +/* pdf_do_page_divert() returns the current /Parent object number */ + +integer pdf_do_page_divert(integer objnum, integer divnum) +{ + divert_list_entry *d; + pages_entry *p; +#ifdef DEBUG + pages_entry *q; + struct avl_traverser t; + int i; +#endif + // initialize the tree + ensure_list_tree(); + // make sure we have a list for this diversion + d = get_divert_list(divnum); + if (d->first == NULL || d->last->number_of_kids == PAGES_TREE_KIDSMAX) { + // append a new pages_entry + p = new_pages_entry(); + if (d->first == NULL) + d->first = p; + else + d->last->next = p; + d->last = p; + } + p = d->last; + p->kids[p->number_of_kids++] = objnum; + p->number_of_pages++; +#ifdef DEBUG + printf("\n"); + avl_t_init(&t, divert_list_tree); + for (d = avl_t_first(&t, divert_list_tree); d != NULL; d = avl_t_next(&t)) { + printf("===== D-LIST %d: ", d->divnum); + for (q = d->first; q != NULL; q = q->next) { + printf("P=%d NK=%d (", q->objnum, q->number_of_kids); + for (i = 0; i < q->number_of_kids; i++) + printf("%d ", q->kids[i]); + printf(") "); + } + printf("\n"); + } + printf("\n"); +#endif + return p->objnum; +} + +static void movelist(divert_list_entry * d, divert_list_entry * dto) +{ + if (d != NULL && d->first != NULL && d->divnum != dto->divnum) { /* no undivert of empty list or into self */ + if (dto->first == NULL) + dto->first = d->first; + else + dto->last->next = d->first; + dto->last = d->last; + d->first = d->last = NULL; /* one could as well remove this divert_list_entry */ + } +} + +/* undivert from diversion <divnum> into diversion <curdivnum> */ + +void pdf_do_page_undivert(integer divnum, integer curdivnum) +{ + divert_list_entry *d, *dto, tmp; + struct avl_traverser t; +#ifdef DEBUG + pages_entry *p; + int i; +#endif + // initialize the tree + ensure_list_tree(); + // find the diversion <curdivnum> list where diversion <divnum> should go + dto = get_divert_list(curdivnum); + if (divnum == 0) { /* 0 = special case: undivert _all_ lists */ + avl_t_init(&t, divert_list_tree); + for (d = avl_t_first(&t, divert_list_tree); d != NULL; + d = avl_t_next(&t)) + movelist(d, dto); + } else { + tmp.divnum = divnum; + d = (divert_list_entry *) avl_find(divert_list_tree, &tmp); + movelist(d, dto); + } +#ifdef DEBUG + printf("\n"); + avl_t_init(&t, divert_list_tree); + for (d = avl_t_first(&t, divert_list_tree); d != NULL; d = avl_t_next(&t)) { + printf("===== U-LIST %d: ", d->divnum); + for (p = d->first; p != NULL; p = p->next) { + printf("P=%d NK=%d (", p->objnum, p->number_of_kids); + for (i = 0; i < p->number_of_kids; i++) + printf("%d ", p->kids[i]); + printf(") "); + } + printf("\n"); + } + printf("\n"); +#endif +} + +/* write a /Pages object */ + +static void write_pages(pages_entry * p, int parent) +{ + int i; + assert(p != NULL); + pdf_begin_dict(p->objnum, 1); + pdf_printf("/Type /Pages\n"); + if (parent == 0) /* it's root */ + print_pdf_pages_attr(); + else + pdf_printf("/Parent %d 0 R\n", parent); + pdf_printf("/Count %d\n/Kids [", (int) p->number_of_pages); + for (i = 0; i < p->number_of_kids; i++) + pdf_printf("%d 0 R ", (int) p->kids[i]); + remove_last_space(); + pdf_printf("]\n"); + pdf_end_dict(); +} + +/* loop over all /Pages objects, output them, create their parents, + * recursing bottom up, return the /Pages root object number */ + +static integer output_pages_list(pages_entry * pe) +{ + pages_entry *p, *q, *r; + assert(pe != NULL); + if (pe->next == NULL) { /* everything fits into one pages_entry */ + write_pages(pe, 0); /* --> /Pages root found */ + return pe->objnum; + } + q = r = new_pages_entry(); /* one level higher needed */ + for (p = pe; p != NULL; p = p->next) { + if (q->number_of_kids == PAGES_TREE_KIDSMAX) { + q->next = new_pages_entry(); + q = q->next; + } + q->kids[q->number_of_kids++] = p->objnum; + q->number_of_pages += p->number_of_pages; + write_pages(p, q->objnum); + } + return output_pages_list(r); /* recurse through next higher level */ +} + +integer output_pages_tree() +{ + divert_list_entry *d; + pdf_do_page_undivert(0, 0); /* concatenate all diversions into diversion 0 */ + d = get_divert_list(0); /* get diversion 0 */ + return output_pages_list(d->first); +} diff --git a/Build/source/texk/web2c/luatexdir/pdf/pdfpage.c b/Build/source/texk/web2c/luatexdir/pdf/pdfpage.c new file mode 100644 index 00000000000..783eabda742 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/pdf/pdfpage.c @@ -0,0 +1,565 @@ +/* pdfpage.c + + Copyright 2006-2009 Taco Hoekwater <taco@luatex.org> + + This file is part of LuaTeX. + + LuaTeX is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + LuaTeX is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU General Public License along + with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ + +/* $Id: pdfpage.c 2046 2009-03-17 20:06:05Z hhenkel $ */ + +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <math.h> + +#include "ptexlib.h" + +static const char __svn_version[] = + "$Id: pdfpage.c 2046 2009-03-17 20:06:05Z hhenkel $ $URL: http://scm.foundry.supelec.fr/svn/luatex/trunk/src/texk/web2c/luatexdir/pdf/pdfpage.c $"; + +#define lround(a) (long) floor((a) + 0.5) +#define setpdffloat(a,b,c) {(a).m = (b); (a).e = (c);} +#define pdf2double(a) ((double) (a).m / exp10[(a).e]) + +/* eternal constants */ +#define one_bp ((double) 65536 * (double) 72.27 / 72) /* number of sp per 1bp */ +#define e_tj 3 /* must be 3; movements in []TJ are in fontsize/10^3 units */ + +/* definitions from luatex.web */ +#define pdf_font_blink(a) font_tables[a]->_pdf_font_blink + +pdfstructure *pstruct = NULL; + +static long *exp10 = NULL; + +/**********************************************************************/ + +static pdfstructure *new_pdfstructure() +{ + return xmalloc(sizeof(pdfstructure)); +} + +static void calc_k1(pdfstructure * p) +{ + p->k1 = exp10[p->pdf.h.e] / one_bp; +} + +static void calc_k2(pdfstructure * p) +{ + p->tm[0].m = + lround(pdf2double(p->hz) * pdf2double(p->ext) * exp10[p->tm[0].e]); + p->k2 = + exp10[e_tj + + p->cw.e] / (exp10[p->pdf.h.e] * pdf2double(p->fs) * + pdf2double(p->tm[0])); +} + +void pdf_page_init() +{ + pdfstructure *p; + int i, decimal_digits = fixed_decimal_digits; + if (exp10 == NULL) { + exp10 = xmalloc(10 * sizeof(long)); + exp10[0] = 1; + for (i = 1; i < 10; i++) + exp10[i] = 10 * exp10[i - 1]; + } + if (pstruct == NULL) + pstruct = new_pdfstructure(); + p = pstruct; + setpdffloat(p->pdf.h, 0, decimal_digits); + setpdffloat(p->pdf.v, 0, decimal_digits); + p->cw.e = 1; + p->fs.e = decimal_digits + 2; /* "+ 2" makes less corrections inside []TJ */ + setpdffloat(p->hz, 1000, 3); /* m = 1000 = default = unexpanded, e must be 3 */ + setpdffloat(p->ext, 1000, 3); /* m = 1000 = default = unextended, e must be 3 */ + /* for placement outside BT...ET */ + setpdffloat(p->cm[0], 1, 0); + setpdffloat(p->cm[1], 0, 0); + setpdffloat(p->cm[2], 0, 0); + setpdffloat(p->cm[3], 1, 0); + setpdffloat(p->cm[4], 0, decimal_digits); /* horizontal movement on page */ + setpdffloat(p->cm[5], 0, decimal_digits); /* vertical movement on page */ + /* for placement inside BT...ET */ + setpdffloat(p->tm[0], exp10[6], 6); /* mantissa holds HZ expand * ExtendFont */ + setpdffloat(p->tm[1], 0, 0); + setpdffloat(p->tm[2], 0, 3); /* mantissa holds SlantFont, 0 = default */ + setpdffloat(p->tm[3], 1, 0); + setpdffloat(p->tm[4], 0, decimal_digits); /* mantissa holds delta from pdf_bt_pos.h */ + setpdffloat(p->tm[5], 0, decimal_digits); /* mantissa holds delta from pdf_bt_pos.v */ + /* */ + p->f_cur = null_font; + p->f_pdf = null_font; + p->wmode = WMODE_H; + p->mode = PMODE_PAGE; + calc_k1(p); +} + +/**********************************************************************/ + +#ifdef SYNCH_POS_WITH_CUR +/* some time this will be needed */ +synch_pos_with_cur(scaledpos * pos, scaledpos * cur, scaledpos * box_pos) +{ + switch (dvi_direction) { + case dir_TL_: + pos->h = box_pos->h + cur->h; + pos->v = box_pos->v - cur->v; + break; + case dir_TR_: + pos->h = box_pos->h - cur->h; + pos->v = box_pos->v - cur->v; + break; + case dir_BL_: + pos->h = box_pos->h + cur->h; + pos->v = box_pos->v + cur->v; + break; + case dir_BR_: + pos->h = box_pos->h - cur->h; + pos->v = box_pos->v + cur->v; + break; + case dir_LT_: + pos->h = box_pos->h + cur->v; + pos->v = box_pos->v - cur->h; + break; + case dir_RT_: + pos->h = box_pos->h - cur->v; + pos->v = box_pos->v - cur->h; + break; + case dir_LB_: + pos->h = box_pos->h + cur->v; + pos->v = box_pos->v + cur->h; + break; + case dir_RB_: + pos->h = box_pos->h - cur->v; + pos->v = box_pos->v + cur->h; + break; + default:; + } +} +#endif + +/**********************************************************************/ + +boolean calc_pdfpos(pdfstructure * p, scaledpos * pos) +{ + scaledpos new; + int move_pdfpos = FALSE; + switch (p->mode) { + case PMODE_PAGE: + new.h = lround(pos->h * p->k1); + new.v = lround(pos->v * p->k1); + p->cm[4].m = new.h - p->pdf.h.m; /* cm is concatenated */ + p->cm[5].m = new.v - p->pdf.v.m; + if (abs(p->cm[4].m) >= 1 || abs(p->cm[5].m) >= 1) + move_pdfpos = TRUE; + break; + case PMODE_TEXT: + new.h = lround(pos->h * p->k1); + new.v = lround(pos->v * p->k1); + p->tm[4].m = new.h - p->pdf_bt_pos.h.m; /* Tm replaces */ + p->tm[5].m = new.v - p->pdf_bt_pos.v.m; + if (abs(p->tm[4].m) >= 1 || abs(p->tm[5].m) >= 1) + move_pdfpos = TRUE; + break; + case PMODE_CHAR: + case PMODE_CHARARRAY: + switch (p->wmode) { + case WMODE_H: + new.h = lround((pos->h * p->k1 - p->pdf_tj_pos.h.m) * p->k2); + new.v = lround(pos->v * p->k1); + p->tj_delta.m = + -lround((new.h - p->cw.m) / exp10[p->cw.e - p->tj_delta.e]); + p->tm[5].m = new.v - p->pdf.v.m; /* p->tm[4] is meaningless */ + if (abs(p->tj_delta.m) >= 1 || abs(p->tm[5].m) >= 1) + move_pdfpos = TRUE; + break; + case WMODE_V: + new.h = lround(pos->h * p->k1); + new.v = lround((p->pdf_tj_pos.v.m - pos->v * p->k1) * p->k2); + p->tm[4].m = new.h - p->pdf.h.m; /* p->tm[5] is meaningless */ + p->tj_delta.m = + -lround((new.v - p->cw.m) / exp10[p->cw.e - p->tj_delta.e]); + if (abs(p->tj_delta.m) >= 1 || abs(p->tm[4].m) >= 1) + move_pdfpos = TRUE; + break; + default: + assert(0); + } + break; + default: + assert(0); + } + return move_pdfpos; +} + +/**********************************************************************/ + +void print_pdffloat(pdffloat * f) +{ + char a[24]; + int e = f->e, i, j; + long l, m = f->m; + if (m < 0) { + pdf_printf("-"); + m *= -1; + } + l = m / exp10[e]; + pdf_print_int(l); + l = m % exp10[e]; + if (l != 0) { + pdf_printf("."); + j = snprintf(a, 23, "%ld", l + exp10[e]); + assert(j < 23); + for (i = e; i > 0; i--) { + if (a[i] != '0') + break; + a[i] = '\0'; + } + pdf_printf("%s", a + 1); + } +} + +static void print_pdf_matrix(pdffloat * tm) +{ + int i; + for (i = 0; i < 5; i++) { + print_pdffloat(tm + i); + pdf_printf(" "); + } + print_pdffloat(tm + i); +} + +void pdf_print_cm(pdffloat * cm) +{ + print_pdf_matrix(cm); + pdf_printf(" cm\n"); +} + +static void pdf_print_tm(pdffloat * tm) +{ + print_pdf_matrix(tm); + pdf_printf(" Tm "); +} + +static void set_pos(pdfstructure * p, scaledpos * pos) +{ + boolean move; + assert(is_pagemode(p)); + move = calc_pdfpos(p, pos); + if (move == TRUE) { + pdf_print_cm(p->cm); + p->pdf.h.m += p->cm[4].m; + p->pdf.v.m += p->cm[5].m; + } +} + +static void set_pos_temp(pdfstructure * p, scaledpos * pos) +{ + boolean move; + assert(is_pagemode(p)); + move = calc_pdfpos(p, pos); + if (move == TRUE) + pdf_print_cm(p->cm); +} + +void pdf_set_pos(scaled h, scaled v) +{ + scaledpos pos; + pos.h = h; + pos.v = v; + set_pos(pstruct, &pos); +} + +void pdf_set_pos_temp(scaled h, scaled v) +{ + scaledpos pos; + pos.h = h; + pos.v = v; + set_pos_temp(pstruct, &pos); +} + +/**********************************************************************/ + +static long pdf_char_width(pdfstructure * p, internal_font_number f, int i) +{ + /* use exactly this formula also for calculating the /Width array values */ + return + lround((double) char_width(f, i) / font_size(f) * + exp10[e_tj + p->cw.e]); +} + +void pdf_print_charwidth(internal_font_number f, int i) +{ + pdffloat cw; + assert(pdf_font_blink(f) == null_font); /* must use unexpanded font! */ + cw.m = pdf_char_width(pstruct, f, i); + cw.e = pstruct->cw.e; + print_pdffloat(&cw); +} + +/**********************************************************************/ + +static void begin_text(pdfstructure * p) +{ + assert(is_pagemode(p)); + p->pdf_bt_pos = p->pdf; + pdf_printf("BT\n"); + p->mode = PMODE_TEXT; +} + +static void end_text(pdfstructure * p) +{ + assert(is_textmode(p)); + pdf_printf("ET\n"); + p->pdf = p->pdf_bt_pos; + p->mode = PMODE_PAGE; +} + +static void begin_charmode(pdfstructure * p) +{ + assert(is_chararraymode(p)); + pdf_printf("("); + p->mode = PMODE_CHAR; +} + +static void end_charmode(pdfstructure * p) +{ + assert(is_charmode(p)); + pdf_printf(")"); + p->mode = PMODE_CHARARRAY; +} + +static void begin_chararray(pdfstructure * p) +{ + assert(is_textmode(p)); + p->pdf_tj_pos = p->pdf; + p->cw.m = 0; + pdf_printf("["); + p->mode = PMODE_CHARARRAY; +} + +static void end_chararray(pdfstructure * p) +{ + assert(is_chararraymode(p)); + pdf_printf("]TJ\n"); + p->pdf = p->pdf_tj_pos; + p->mode = PMODE_TEXT; +} + +void pdf_end_string_nl() +{ + if (is_charmode(pstruct)) + end_charmode(pstruct); + if (is_chararraymode(pstruct)) + end_chararray(pstruct); +} + +/**********************************************************************/ + +static void goto_pagemode(pdfstructure * p) +{ + if (!is_pagemode(p)) { + if (is_charmode(p)) + end_charmode(p); + if (is_chararraymode(p)) + end_chararray(p); + if (is_textmode(p)) + end_text(p); + assert(is_pagemode(p)); + } +} + +void pdf_goto_pagemode() +{ + goto_pagemode(pstruct); +} + +static void goto_textmode(pdfstructure * p) +{ + scaledpos origin = { + 0, 0 + }; + if (!is_textmode(p)) { + if (is_pagemode(p)) { + set_pos(p, &origin); /* reset to page origin */ + begin_text(p); + } else { + if (is_charmode(p)) + end_charmode(p); + if (is_chararraymode(p)) + end_chararray(p); + } + assert(is_textmode(p)); + } +} + +void pos_finish(pdfstructure * p) +{ + goto_pagemode(p); +} + +/**********************************************************************/ + +static void place_rule(pdfstructure * p, scaledpos * pos, scaled wd, scaled ht) +{ + pdfpos dim; + scaledpos tmppos = *pos; + goto_pagemode(p); + dim.h.m = lround(wd * p->k1); + dim.h.e = p->pdf.h.e; + dim.v.m = lround(ht * p->k1); + dim.v.e = p->pdf.v.e; + pdf_printf("q\n"); + if (ht <= one_bp) { + tmppos.v += lround(0.5 * ht); + set_pos_temp(p, &tmppos); + pdf_printf("[]0 d 0 J "); + print_pdffloat(&(dim.v)); + pdf_printf(" w 0 0 m "); + print_pdffloat(&(dim.h)); + pdf_printf(" 0 l S\n"); + } else if (wd <= one_bp) { + tmppos.h += lround(0.5 * wd); + set_pos_temp(p, &tmppos); + pdf_printf("[]0 d 0 J "); + print_pdffloat(&(dim.h)); + pdf_printf(" w 0 0 m 0 "); + print_pdffloat(&(dim.v)); + pdf_printf(" l S\n"); + } else { + set_pos_temp(p, &tmppos); + pdf_printf("0 0 "); + print_pdffloat(&(dim.h)); + pdf_printf(" "); + print_pdffloat(&(dim.v)); + pdf_printf(" re f\n"); + } + pdf_printf("Q\n"); +} + +void pdf_place_rule(scaled h, scaled v, scaled wd, scaled ht) +{ + scaledpos pos; + pos.h = h; + pos.v = v; + place_rule(pstruct, &pos, wd, ht); +} + +/**********************************************************************/ + +static void setup_fontparameters(pdfstructure * p, internal_font_number f) +{ + p->f_cur = f; + p->f_pdf = pdf_set_font(f); + p->tj_delta.e = p->cw.e - 1; /* "- 1" makes less corrections inside []TJ */ + /* no need to be more precise than TeX (1sp) */ + while (p->tj_delta.e > 0 + && (double) font_size(f) / exp10[p->tj_delta.e + e_tj] < 0.5) + p->tj_delta.e--; /* happens for very tiny fonts */ + assert(p->cw.e >= p->tj_delta.e); /* else we would need, e. g., exp10[-1] */ + p->fs.m = lround(font_size(f) / one_bp * exp10[p->fs.e]); + p->hz.m = pdf_font_expand_ratio(f) + exp10[p->hz.e]; + calc_k2(p); +} + +static void set_textmatrix(pdfstructure * p, scaledpos * pos) +{ + boolean move; + assert(is_textmode(p)); + move = calc_pdfpos(p, pos); + if (move == TRUE) { + pdf_print_tm(p->tm); + p->pdf.h.m = p->pdf_bt_pos.h.m + p->tm[4].m; /* Tm replaces */ + p->pdf.v.m = p->pdf_bt_pos.v.m + p->tm[5].m; + } +} + +static void set_font(pdfstructure * p) +{ + pdf_printf("/F%d", p->f_pdf); + pdf_print_resname_prefix(); + pdf_printf(" "); + print_pdffloat(&(p->fs)); + pdf_printf(" Tf "); +} + +/**********************************************************************/ + +static void +place_glyph(pdfstructure * p, scaledpos * pos, internal_font_number f, + integer c) +{ + int move; + if (f != p->f_cur || is_textmode(p) || is_pagemode(p)) { + goto_textmode(p); + if (f != p->f_cur) + setup_fontparameters(p, f); + set_font(p); + set_textmatrix(p, pos); + begin_chararray(p); + } + assert(is_charmode(p) || is_chararraymode(p)); + move = calc_pdfpos(p, pos); + if (move == TRUE) { + if ((p->wmode == WMODE_H && abs(p->tm[5].m) >= 1) + || (p->wmode == WMODE_V && abs(p->tm[4].m) >= 1) + || abs(p->tj_delta.m) >= 1000000) { + goto_textmode(p); + set_textmatrix(p, pos); + begin_chararray(p); + move = calc_pdfpos(p, pos); + } + assert((p->wmode == WMODE_H && p->tm[5].m == 0) + || (p->wmode == WMODE_V && p->tm[4].m == 0)); + if (move == TRUE) { + if (is_charmode(p)) + end_charmode(p); + assert(abs(p->tj_delta.m) >= 1); + print_pdffloat(&(p->tj_delta)); + p->cw.m -= p->tj_delta.m * exp10[p->cw.e - p->tj_delta.e]; + } + } + if (is_chararraymode(p)) + begin_charmode(p); + pdf_print_char(f, c); /* this also does pdf_mark_char() */ + p->cw.m += pdf_char_width(p, p->f_pdf, c); /* aka adv_char_width() */ +} + +void pdf_place_glyph(internal_font_number f, integer c) +{ + if (char_exists(f, c)) + place_glyph(pstruct, &pos, f, c); +} + +/**********************************************************************/ + +static void place_form(pdfstructure * p, scaledpos * pos, integer i) +{ + goto_pagemode(p); + pdf_printf("q\n"); + set_pos_temp(p, pos); + pdf_printf("/Fm%d", i); + pdf_print_resname_prefix(); + pdf_printf(" Do\nQ\n"); +} + +void pdf_place_form(scaled h, scaled v, integer i) +{ + scaledpos pos; + pos.h = h; + pos.v = v; + place_form(pstruct, &pos, i); +} |