Hey, LuaTeX currently supports only a very special kind of Type 3 fonts: They are generated for traditional TeX bitmap fonts. While this used to be the most common use case for Type3 fonts, the fully general concept of these fonts has recently been reinvented under the name of SVG fonts (and friends). While they can be implemented in LuaTeX to some degree through virtual fonts/node processing etc., converting them into "real" Type 3 fonts in the PDF file would give some important advantages: Such fonts are called like other fonts and can get tounicode vectors, allowing better accessibillity and better Copy&Paste behaviour. Also viewers generally treat them as text instead of graphics, allowing proper interaction with features of PDF viewers. Beside from supporting SVG fonts, it also allows to use general MetaPost fonts which might not be easily convertable into normal formats for vector fonts.
As far as I can tell there used to be an implementation of general Type 3 fonts for pdfTeX which was dropped in LuaTeX, mostly because it was never actually used. My suggested new implementation is a bit more flexible by not requiring external files defining the font but instead generating each font character based on individual node lists for every glyph. One way to make this work would be to add a special `format` named e.g. `node` (given that `type3` is already used to imply bitmap fonts) and add a field `node`/`list`/`head` to the character table referencing a node list which should become the font glyph. The detaily like bounding box calculations etc. would be the responsibility of the Lua code loading the font. The intended usage would be e.g. \directlua{ local l = token.scan_list() local wi = node.new('whatsit', 'pdf_literal') wi.mode = 3 wi.data = math.floor(l.width / tex.sp'1bp') .. ' 0 d0' wi.next = l.head l.head = wi font.current(font.define{ name = "exp-nodefont", format = "node", designsize = tex.sp("10pt"), size = tex.sp("10pt"), characters = { [42] = { width = l.width, height = l.height, depth = l.depth, node = node.direct.todirect(l), } } })}\hbox{ABC} \char42 \char42 \bye What do you think? (I'll attach a patch I used for experiments (mostly with MetaPost fonts) which implements this in a slightly hacky way.) -- Marcel
>From 81022d5f885626cd64188f8448b33df0fb065317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Fabian=20Kr=C3=BCger?= <t...@2krueger.de> Date: Mon, 21 Jan 2019 22:00:11 +0100 Subject: [PATCH] Node fonts --- source/texk/web2c/luatexdir/font/luafont.c | 26 ++- source/texk/web2c/luatexdir/font/texfont.c | 2 +- source/texk/web2c/luatexdir/font/texfont.h | 7 +- source/texk/web2c/luatexdir/font/writet3.c | 138 ++++++++++++--- source/texk/web2c/luatexdir/pdf/pdffont.c | 3 + source/texk/web2c/luatexdir/pdf/pdfgen.c | 170 ++++++++++++++----- source/texk/web2c/luatexdir/pdf/pdfgen.h | 2 + source/texk/web2c/luatexdir/pdf/pdfglyph.c | 25 +++ source/texk/web2c/luatexdir/pdf/pdfglyph.h | 1 + source/texk/web2c/luatexdir/pdf/pdfshipout.c | 8 +- source/texk/web2c/luatexdir/pdf/pdftypes.h | 5 +- source/texk/web2c/luatexdir/ptexlib.h | 7 +- 12 files changed, 302 insertions(+), 92 deletions(-) diff --git a/source/texk/web2c/luatexdir/font/luafont.c b/source/texk/web2c/luatexdir/font/luafont.c index 62edb1758..96ef0e8d6 100644 --- a/source/texk/web2c/luatexdir/font/luafont.c +++ b/source/texk/web2c/luatexdir/font/luafont.c @@ -43,7 +43,7 @@ const char *font_identity_strings[] = { }; const char *font_format_strings[] = { - "unknown", "type1", "type3", "truetype", "opentype", NULL + "unknown", "type1", "type3", "truetype", "opentype", "node", NULL }; const char *font_embedding_strings[] = { @@ -198,7 +198,9 @@ static void font_char_to_lua(lua_State * L, internal_font_number f, charinfo * c if (get_charinfo_rp(co) != 0) { dump_intfield(L,right_protruding,get_charinfo_rp(co)); } - if (font_encodingbytes(f) == 2) { + if (font_format(f) == node_format) { + dump_intfield(L,node,get_charinfo_index(co)); + } else if (font_encodingbytes(f) == 2) { dump_intfield(L,index,get_charinfo_index(co)); } if (get_charinfo_name(co) != NULL) { @@ -1130,7 +1132,7 @@ static void store_math_kerns(lua_State * L, int index, charinfo * co, int id) lua_pop(L, 1); } -static void font_char_from_lua(lua_State * L, internal_font_number f, int i, int *l_fonts, boolean has_math) +static void font_char_from_lua(lua_State * L, internal_font_number f, int i, int *l_fonts, boolean has_math, boolean is_nodefont) { int k, r, t, lt, u, n; charinfo *co; @@ -1157,7 +1159,11 @@ static void font_char_from_lua(lua_State * L, internal_font_number f, int i, int set_charinfo_italic(co, j); j = lua_numeric_field_by_index(L, lua_key_index(vert_italic), 0); set_charinfo_vert_italic(co, j); - j = lua_numeric_field_by_index(L, lua_key_index(index), 0); + if (is_nodefont) { + j = lua_numeric_field_by_index(L, lua_key_index(node), 0); + } else { + j = (unsigned short) lua_numeric_field_by_index(L, lua_key_index(index), 0); + } set_charinfo_index(co, j); j = lua_numeric_field_by_index(L, lua_key_index(expansion_factor), 1000); set_charinfo_ef(co, j); @@ -1455,6 +1461,7 @@ int font_from_lua(lua_State * L, int f) int *l_fonts = NULL; int save_ref ; boolean no_math = false; + boolean is_nodefont = false; /*tex Will we save a cache of the \LUA\ table? */ save_ref = 1; ss = NULL; @@ -1545,6 +1552,9 @@ int font_from_lua(lua_State * L, int f) set_font_type(f, i); i = n_enum_field(L, lua_key_index(format), unknown_format, font_format_strings); set_font_format(f, i); + if (i == node_format) { + is_nodefont = true; + } i = n_enum_field(L, lua_key_index(writingmode), unknown_writingmode, font_writingmode_strings); set_font_writingmode(f, i); i = n_enum_field(L, lua_key_index(identity), unknown_identity, font_identity_strings); @@ -1664,14 +1674,14 @@ int font_from_lua(lua_State * L, int f) if (lt == LUA_TNUMBER) { i = (int) lua_tointeger(L, -2); if (i >= 0) { - font_char_from_lua(L, f, i, l_fonts, !no_math); + font_char_from_lua(L, f, i, l_fonts, !no_math, is_nodefont); } } else if (lt == LUA_TSTRING) { const char *ss1 = lua_tostring(L, -2); if (lua_key_eq(ss1, left_boundary)) { - font_char_from_lua(L, f, left_boundarychar, l_fonts, !no_math); + font_char_from_lua(L, f, left_boundarychar, l_fonts, !no_math, is_nodefont); } else if (lua_key_eq(ss1, right_boundary)) { - font_char_from_lua(L, f, right_boundarychar, l_fonts, !no_math); + font_char_from_lua(L, f, right_boundarychar, l_fonts, !no_math, is_nodefont); } } lua_pop(L, 1); @@ -1844,7 +1854,7 @@ int characters_from_lua(lua_State * L, int f) set_charinfo_vert_variants(co, NULL); set_charinfo_hor_variants(co, NULL); } - font_char_from_lua(L, f, i, l_fonts, !no_math); + font_char_from_lua(L, f, i, l_fonts, !no_math, font_format(f) == node_format); } } lua_pop(L, 1); diff --git a/source/texk/web2c/luatexdir/font/texfont.c b/source/texk/web2c/luatexdir/font/texfont.c index 332a8a344..a25f8ef37 100644 --- a/source/texk/web2c/luatexdir/font/texfont.c +++ b/source/texk/web2c/luatexdir/font/texfont.c @@ -564,7 +564,7 @@ void set_charinfo_used(charinfo * ci, scaled val) void set_charinfo_index(charinfo * ci, scaled val) { - ci->index = (unsigned short) val; + ci->index = val; } void set_charinfo_name(charinfo * ci, char *val) diff --git a/source/texk/web2c/luatexdir/font/texfont.h b/source/texk/web2c/luatexdir/font/texfont.h index 2622b7a14..8f1b0bea7 100644 --- a/source/texk/web2c/luatexdir/font/texfont.h +++ b/source/texk/web2c/luatexdir/font/texfont.h @@ -85,7 +85,7 @@ typedef struct charinfo { liginfo *ligatures; /* ligature items */ kerninfo *kerns; /* kern items */ eight_bits *packets; /* virtual commands. */ - unsigned short index; /* CID index */ + halfword index; /* CID index or nodelist reference */ int remainder; /* spare value for odd items, could be union-ed with extensible */ scaled width; /* width */ scaled height; /* height */ @@ -190,6 +190,7 @@ typedef struct texfont { int _pdf_font_num; /* maps to a PDF resource ID */ str_number _pdf_font_attr; /* pointer to additional attributes */ + struct avl_table *_pdf_resources; } texfont; typedef enum { @@ -204,6 +205,7 @@ typedef enum { type3_format, truetype_format, opentype_format, + node_format, } font_formats; typedef enum { @@ -385,6 +387,9 @@ boolean cmp_font_area(int, str_number); # define pdf_font_attr(a) font_tables[a]->_pdf_font_attr # define set_pdf_font_attr(a,b) pdf_font_attr(a) = b +# define pdf_font_resources(a) font_tables[a]->_pdf_resources +# define set_pdf_font_resources(a,b) pdf_font_resources(a) = b + # define left_boundarychar -1 # define right_boundarychar -2 # define non_boundarychar -3 diff --git a/source/texk/web2c/luatexdir/font/writet3.c b/source/texk/web2c/luatexdir/font/writet3.c index 6121c24a1..6fd02da15 100644 --- a/source/texk/web2c/luatexdir/font/writet3.c +++ b/source/texk/web2c/luatexdir/font/writet3.c @@ -206,6 +206,28 @@ static boolean writepk(PDF pdf, internal_font_number f) return true; } +static boolean writet3nodes(PDF pdf, internal_font_number f) +{ + shipping_mode_e save_shipping_mode = global_shipping_mode; + int save_pdf_cur_form = pdf_cur_form; + scaledpos save_cur_page_size = pdf->page_size; + global_shipping_mode = SHIPPING_FORM; + t3_image_used = false; + is_pk_font = false; + t3_font_scale = by_one_bp / font_dsize(f); + for (int i = font_bc(f); i <= font_ec(f); i++) { + if (!pdf_char_marked(f, i)) + continue; + t3_char_widths[i] = (float) divide_scaled(ext_xn_over_d(get_charwidth(f, i), font_dsize(f), font_size(f)),one_hundred_bp,4); + t3_glyph_num++; + t3_char_procs[i] = char_index(f, i); + } + pdf->page_size = save_cur_page_size; + pdf_cur_form = save_pdf_cur_form; + global_shipping_mode = save_shipping_mode; + return true; +} + void writet3(PDF pdf, internal_font_number f) { int i; @@ -213,6 +235,7 @@ void writet3(PDF pdf, internal_font_number f) int wptr, eptr, cptr; int first_char, last_char; int pk_font_scale; + int procset = PROCSET_PDF; pdffloat pf; boolean is_notdef; t3_glyph_num = 0; @@ -222,11 +245,13 @@ void writet3(PDF pdf, internal_font_number f) t3_char_widths[i] = 0; } is_pk_font = false; - xfree(t3_buffer); - t3_curbyte = 0; - t3_size = 0; - if (!writepk(pdf, f)) - return; + if (font_format(f) == node_format) { + if (!writet3nodes(pdf, f)) + return; + } else { + if (!writepk(pdf, f)) + return; + } for (i = font_bc(f); i <= font_ec(f); i++) if (pdf_char_marked(f, i)) break; @@ -263,22 +288,85 @@ void writet3(PDF pdf, internal_font_number f) pdf_printf(pdf, "%g 0 0 %g 0 0", (double) t3_font_scale, (double) t3_font_scale); pdf_end_array(pdf); } - pdf_add_name(pdf, font_key[FONTBBOX1_CODE].pdfname); - pdf_begin_array(pdf); - pdf_add_int(pdf, (int) t3_b0); - pdf_add_int(pdf, (int) t3_b1); - pdf_add_int(pdf, (int) t3_b2); - pdf_add_int(pdf, (int) t3_b3); - pdf_end_array(pdf); + if (is_pk_font) { + pdf_add_name(pdf, font_key[FONTBBOX1_CODE].pdfname); + pdf_begin_array(pdf); + pdf_add_int(pdf, (int) t3_b0); + pdf_add_int(pdf, (int) t3_b1); + pdf_add_int(pdf, (int) t3_b2); + pdf_add_int(pdf, (int) t3_b3); + pdf_end_array(pdf); + } pdf_add_name(pdf, "Resources"); pdf_begin_dict(pdf); - pdf_add_name(pdf, "ProcSet"); - pdf_begin_array(pdf); - pdf_add_name(pdf, "PDF"); - if (t3_image_used) { - pdf_add_name(pdf, "ImageB"); + /*tex Generate font resources. */ + if (!is_pk_font && pdf_font_resources(f)) { + char s[64], *p; + pdf_object_list *ol, *ol1; + if ((ol = get_resources_list(pdf_font_resources(f), obj_type_font))) { + pdf_add_name(pdf, "Font"); + pdf_begin_dict(pdf); + while (ol != NULL) { + p = s; + p += snprintf(p, 20, "F%i", obj_info(pdf, ol->info)); + if (pdf->resname_prefix != NULL) + p += snprintf(p, 20, "%s", pdf->resname_prefix); + pdf_dict_add_ref(pdf, s, ol->info); + ol = ol->link; + } + pdf_end_dict(pdf); + procset |= PROCSET_TEXT; + } + /*tex Generate |XObject| resources. */ + ol = get_resources_list(pdf_font_resources(f), obj_type_xform); + ol1 = get_resources_list(pdf_font_resources(f), obj_type_ximage); + if (ol != NULL || ol1 != NULL) { + pdf_add_name(pdf, "XObject"); + pdf_begin_dict(pdf); + while (ol != NULL) { + p = s; + p += snprintf(p, 20, "Fm%i", obj_info(pdf, ol->info)); + if (pdf->resname_prefix != NULL) + p += snprintf(p, 20, "%s", pdf->resname_prefix); + pdf_dict_add_ref(pdf, s, ol->info); + ol = ol->link; + } + while (ol1 != null) { + p = s; + p += snprintf(p, 20, "Im%i", obj_info(pdf, ol1->info)); + if (pdf->resname_prefix != NULL) + p += snprintf(p, 20, "%s", pdf->resname_prefix); + pdf_dict_add_ref(pdf, s, ol1->info); + procset |= img_procset(idict_array[obj_data_ptr(pdf, ol1->info)]); + ol1 = ol1->link; + } + pdf_end_dict(pdf); + } + /*tex Generate |ProcSet| in version 1.*/ + if (pdf->major_version == 1) { + pdf_add_name(pdf, "ProcSet"); + pdf_begin_array(pdf); + if ((procset & PROCSET_PDF) != 0) + pdf_add_name(pdf, "PDF"); + if ((procset & PROCSET_TEXT) != 0) + pdf_add_name(pdf, "Text"); + if ((procset & PROCSET_IMAGE_B) != 0) + pdf_add_name(pdf, "ImageB"); + if ((procset & PROCSET_IMAGE_C) != 0) + pdf_add_name(pdf, "ImageC"); + if ((procset & PROCSET_IMAGE_I) != 0) + pdf_add_name(pdf, "ImageI"); + pdf_end_array(pdf); + } + } else { + pdf_add_name(pdf, "ProcSet"); + pdf_begin_array(pdf); + pdf_add_name(pdf, "PDF"); + if (t3_image_used) { + pdf_add_name(pdf, "ImageB"); + } + pdf_end_array(pdf); } - pdf_end_array(pdf); pdf_end_dict(pdf); pdf_dict_add_int(pdf, "FirstChar", first_char); pdf_dict_add_int(pdf, "LastChar", last_char); @@ -293,16 +381,10 @@ void writet3(PDF pdf, internal_font_number f) /*tex The |Widths| array: */ pdf_begin_obj(pdf, wptr, OBJSTM_ALWAYS); pdf_begin_array(pdf); - if (is_pk_font) { - for (i = first_char; i <= last_char; i++) { - setpdffloat(pf, (int64_t) t3_char_widths[i], 2); - print_pdffloat(pdf, pf); - pdf_out(pdf, ' '); - } - } else { - for (i = first_char; i <= last_char; i++) { - pdf_add_int(pdf, (int) t3_char_widths[i]); - } + for (i = first_char; i <= last_char; i++) { + setpdffloat(pf, (int64_t) t3_char_widths[i], 2); + print_pdffloat(pdf, pf); + pdf_out(pdf, ' '); } pdf_end_array(pdf); pdf_end_obj(pdf); diff --git a/source/texk/web2c/luatexdir/pdf/pdffont.c b/source/texk/web2c/luatexdir/pdf/pdffont.c index 1e1f0f8d9..4cd496cb3 100644 --- a/source/texk/web2c/luatexdir/pdf/pdffont.c +++ b/source/texk/web2c/luatexdir/pdf/pdffont.c @@ -165,6 +165,9 @@ void pdf_init_font(PDF pdf, internal_font_number f) } i = obj_link(pdf, i); } + if(font_format(f) == node_format) { + set_pdf_font_resources(f, NULL); + } /*tex Create a new font object for |f|: */ l = pdf_create_obj(pdf, obj_type_font, f); pdf_use_font(f, l); diff --git a/source/texk/web2c/luatexdir/pdf/pdfgen.c b/source/texk/web2c/luatexdir/pdf/pdfgen.c index 3d37102b2..52227489b 100644 --- a/source/texk/web2c/luatexdir/pdf/pdfgen.c +++ b/source/texk/web2c/luatexdir/pdf/pdfgen.c @@ -811,19 +811,66 @@ void addto_page_resources(PDF pdf, pdf_obj_type t, int k) } } -pdf_object_list *get_page_resources_list(PDF pdf, pdf_obj_type t) +static void merge_page_resources(PDF pdf, pdf_obj_type t, struct avl_table **destination) +{ + pr_entry *pr, tmp, *src; + void **pp; + pdf_object_list *p, *item = NULL, *tail = NULL; + tmp.obj_type = t; + if (!pdf->page_resources || !pdf->page_resources->resources_tree) return; + src = (pr_entry *) avl_find(pdf->page_resources->resources_tree, &tmp); + if (!src) return; + if (*destination == NULL) { + *destination = avl_create(comp_page_resources, NULL, &avl_xallocator); + if (*destination == NULL) + formatted_error("pdf backend","marge_page_resources(): avl_create() page_resource_tree failed"); + } + pr = (pr_entry *) avl_find(*destination, &tmp); + if (pr == NULL) { + pr = xtalloc(1, pr_entry); + pr->obj_type = t; + pr->list = NULL; + pp = avl_probe(*destination, pr); + if (pp == NULL) + formatted_error("pdf backend","addto_page_resources(): avl_probe() out of memory in insertion"); + } + if (pr->list == NULL) { + pr->list = src->list; + src->list = NULL; + } else { + while (src->list) { + item = src->list; + src->list = item->link; + for (p = pr->list; p->info != item->info && p->link != tail; p = p->link); + if (p->info == item->info) { + free(item); + } else { + if (tail == NULL) tail = p; + item->link = NULL; + p->link = item; + } + } + } +} + +pdf_object_list *get_resources_list(struct avl_table *rt, pdf_obj_type t) { - pdf_resource_struct *re = pdf->page_resources; pr_entry *pr, tmp; - if (re == NULL || re->resources_tree == NULL) - return NULL; tmp.obj_type = t; - pr = (pr_entry *) avl_find(re->resources_tree, &tmp); + pr = (pr_entry *) avl_find(rt, &tmp); if (pr == NULL) return NULL; return pr->list; } +pdf_object_list *get_page_resources_list(PDF pdf, pdf_obj_type t) +{ + pdf_resource_struct *re = pdf->page_resources; + if (re == NULL || re->resources_tree == NULL) + return NULL; + return get_resources_list(re->resources_tree, t); +} + static void reset_page_resources(PDF pdf) { pdf_resource_struct *re = pdf->page_resources; @@ -1640,7 +1687,8 @@ void pdf_begin_page(PDF pdf) pdf->page_resources = xtalloc(1, pdf_resource_struct); pdf->page_resources->resources_tree = NULL; } - pdf->page_resources->last_resources = pdf_create_obj(pdf, obj_type_others, 0); + if (global_shipping_mode != SHIPPING_GLYPH) + pdf->page_resources->last_resources = pdf_create_obj(pdf, obj_type_others, 0); reset_page_resources(pdf); if (global_shipping_mode == SHIPPING_PAGE) { @@ -1652,52 +1700,54 @@ void pdf_begin_page(PDF pdf) pdf->last_thread = null; pdf_begin_dict(pdf); } else { - xform_type = obj_xform_type(pdf, pdf_cur_form) ; pdf_begin_obj(pdf, pdf_cur_form, OBJSTM_NEVER); pdf->last_stream = pdf_cur_form; /*tex Write out the |Form| stream header */ pdf_begin_dict(pdf); - if (xform_type == 0) { - pdf_dict_add_name(pdf, "Type", "XObject"); - pdf_dict_add_name(pdf, "Subtype", "Form"); - pdf_dict_add_int(pdf, "FormType", 1); - } - xform_attributes = pdf_xform_attr; - /*tex Now stored in the object: */ - form_margin = obj_xform_margin(pdf, pdf_cur_form); - if (xform_attributes != null) - pdf_print_toks(pdf, xform_attributes); - if (obj_xform_attr(pdf, pdf_cur_form) != null) { - pdf_print_toks(pdf, obj_xform_attr(pdf, pdf_cur_form)); - delete_token_ref(obj_xform_attr(pdf, pdf_cur_form)); - set_obj_xform_attr(pdf, pdf_cur_form, null); - } - if (obj_xform_attr_str(pdf, pdf_cur_form) != null) { - lua_pdf_literal(pdf, obj_xform_attr_str(pdf, pdf_cur_form),1); - luaL_unref(Luas, LUA_REGISTRYINDEX, obj_xform_attr_str(pdf, pdf_cur_form)); - set_obj_xform_attr_str(pdf, pdf_cur_form, null); - } - if (xform_type == 0 || xform_type == 1 || xform_type == 3) { - pdf_add_name(pdf, "BBox"); - pdf_begin_array(pdf); - pdf_add_bp(pdf, -form_margin); - pdf_add_bp(pdf, -form_margin); - pdf_add_bp(pdf, pdf->page_size.h + form_margin); - pdf_add_bp(pdf, pdf->page_size.v + form_margin); - pdf_end_array(pdf); - } - if (xform_type == 0 || xform_type == 2 || xform_type == 3) { - pdf_add_name(pdf, "Matrix"); - pdf_begin_array(pdf); - pdf_add_int(pdf, 1); - pdf_add_int(pdf, 0); - pdf_add_int(pdf, 0); - pdf_add_int(pdf, 1); - pdf_add_int(pdf, 0); - pdf_add_int(pdf, 0); - pdf_end_array(pdf); + if(global_shipping_mode == SHIPPING_FORM) { + xform_type = obj_xform_type(pdf, pdf_cur_form) ; + if (xform_type == 0) { + pdf_dict_add_name(pdf, "Type", "XObject"); + pdf_dict_add_name(pdf, "Subtype", "Form"); + pdf_dict_add_int(pdf, "FormType", 1); + } + xform_attributes = pdf_xform_attr; + /*tex Now stored in the object: */ + form_margin = obj_xform_margin(pdf, pdf_cur_form); + if (xform_attributes != null) + pdf_print_toks(pdf, xform_attributes); + if (obj_xform_attr(pdf, pdf_cur_form) != null) { + pdf_print_toks(pdf, obj_xform_attr(pdf, pdf_cur_form)); + delete_token_ref(obj_xform_attr(pdf, pdf_cur_form)); + set_obj_xform_attr(pdf, pdf_cur_form, null); + } + if (obj_xform_attr_str(pdf, pdf_cur_form) != null) { + lua_pdf_literal(pdf, obj_xform_attr_str(pdf, pdf_cur_form),1); + luaL_unref(Luas, LUA_REGISTRYINDEX, obj_xform_attr_str(pdf, pdf_cur_form)); + set_obj_xform_attr_str(pdf, pdf_cur_form, null); + } + if (xform_type == 0 || xform_type == 1 || xform_type == 3) { + pdf_add_name(pdf, "BBox"); + pdf_begin_array(pdf); + pdf_add_bp(pdf, -form_margin); + pdf_add_bp(pdf, -form_margin); + pdf_add_bp(pdf, pdf->page_size.h + form_margin); + pdf_add_bp(pdf, pdf->page_size.v + form_margin); + pdf_end_array(pdf); + } + if (xform_type == 0 || xform_type == 2 || xform_type == 3) { + pdf_add_name(pdf, "Matrix"); + pdf_begin_array(pdf); + pdf_add_int(pdf, 1); + pdf_add_int(pdf, 0); + pdf_add_int(pdf, 0); + pdf_add_int(pdf, 1); + pdf_add_int(pdf, 0); + pdf_add_int(pdf, 0); + pdf_end_array(pdf); + } + pdf_dict_add_ref(pdf, "Resources", pdf->page_resources->last_resources); } - pdf_dict_add_ref(pdf, "Resources", pdf->page_resources->last_resources); } /*tex Start a stream of page or form contents: */ pdf_dict_add_streaminfo(pdf); @@ -1875,6 +1925,25 @@ void pdf_end_page(PDF pdf) } ol = ol->link; } + ol = get_page_resources_list(pdf, obj_type_glyph); + while (ol != NULL) { + if (!is_obj_written(pdf, ol->info)) { + save_pdf_cur_form = pdf_cur_form; + pdf_cur_form = ol->info; + save_cur_page_size = pdf->page_size; + save_shipping_mode = global_shipping_mode; + pdf->page_resources = &local_page_resources; + local_page_resources.resources_tree = NULL; + ship_out(pdf, obj_xform_box(pdf, pdf_cur_form), SHIPPING_GLYPH); + /*tex Restore the page size and page resources. */ + pdf->page_size = save_cur_page_size; + global_shipping_mode = save_shipping_mode; + destroy_page_resources_tree(pdf); + pdf->page_resources = res_p; + pdf_cur_form = save_pdf_cur_form; + } + ol = ol->link; + } /*tex Write out pending images. */ ol = get_page_resources_list(pdf, obj_type_ximage); while (ol != NULL) { @@ -1937,6 +2006,13 @@ void pdf_end_page(PDF pdf) /*tex Write out \PDF\ bead rectangle specifications. */ print_bead_rectangles(pdf); } + if (global_shipping_mode == SHIPPING_GLYPH) { + /*tex Merge resources into font resources. */ + merge_page_resources(pdf, obj_type_font, &pdf_font_resources(obj_xform_type(pdf, pdf_cur_form))); + merge_page_resources(pdf, obj_type_xform, &pdf_font_resources(obj_xform_type(pdf, pdf_cur_form))); + merge_page_resources(pdf, obj_type_ximage, &pdf_font_resources(obj_xform_type(pdf, pdf_cur_form))); + return; + } /*tex Write out resources dictionary. */ pdf_begin_obj(pdf, res_p->last_resources, OBJSTM_ALWAYS); pdf_begin_dict(pdf); diff --git a/source/texk/web2c/luatexdir/pdf/pdfgen.h b/source/texk/web2c/luatexdir/pdf/pdfgen.h index 00df7f36e..69b3a4966 100644 --- a/source/texk/web2c/luatexdir/pdf/pdfgen.h +++ b/source/texk/web2c/luatexdir/pdf/pdfgen.h @@ -68,6 +68,7 @@ be the first written bytes. typedef enum { /* needs pdf_prefix */ NOT_SHIPPING, SHIPPING_PAGE, + SHIPPING_GLYPH, SHIPPING_FORM } shipping_mode_e; @@ -179,6 +180,7 @@ extern void strbuf_free(strbuf_s * b); extern void addto_page_resources(PDF pdf, pdf_obj_type t, int k); extern pdf_object_list *get_page_resources_list(PDF pdf, pdf_obj_type t); +extern pdf_object_list *get_resources_list(struct avl_table *rt, pdf_obj_type t); extern void pdf_out_block(PDF pdf, const char *s, size_t n); diff --git a/source/texk/web2c/luatexdir/pdf/pdfglyph.c b/source/texk/web2c/luatexdir/pdf/pdfglyph.c index c7cf04392..94e2cc856 100644 --- a/source/texk/web2c/luatexdir/pdf/pdfglyph.c +++ b/source/texk/web2c/luatexdir/pdf/pdfglyph.c @@ -287,3 +287,28 @@ void pdf_place_glyph(PDF pdf, internal_font_number f, int c, int ex) /*tex Also known as |adv_char_width()|: */ p->cw.m += pdf_char_width(p, p->f_pdf, c); } + +void pdf_ship_node_char(PDF pdf, internal_font_number f, int c) { + int objnum; + if (pdf_font_num(f) < 0) { + pdf_mark_char(-pdf_font_num(f), c); + return; + } + if (!char_exists(f, c)) return; + if (!pdf_char_marked(f, c)) { + pdf->xform_count++; + objnum = pdf_create_obj(pdf, obj_type_glyph, pdf->xform_count); + set_obj_data_ptr(pdf, objnum, pdf_get_mem(pdf, pdfmem_xform_size)); + set_obj_xform_type(pdf, objnum, f); + set_obj_xform_margin(pdf, objnum, pdf_xform_margin); + assert(char_index(f, c) >= 0); + if (char_index(f, c) == null) + normal_error("pdf backend", "a node glyph needs a node"); + set_obj_xform_box(pdf, objnum, char_index(f, c)); + set_charinfo_index(get_charinfo(f, c), objnum); + if (global_shipping_mode == NOT_SHIPPING) + ship_out(pdf, char_index(f, c), SHIPPING_GLYPH); + else + addto_page_resources(pdf, obj_type_glyph, objnum); + } +} diff --git a/source/texk/web2c/luatexdir/pdf/pdfglyph.h b/source/texk/web2c/luatexdir/pdf/pdfglyph.h index 2d04e944c..29430bfd2 100644 --- a/source/texk/web2c/luatexdir/pdf/pdfglyph.h +++ b/source/texk/web2c/luatexdir/pdf/pdfglyph.h @@ -21,6 +21,7 @@ #ifndef PDFGLYPH_H # define PDFGLYPH_H +void pdf_ship_node_char(PDF pdf, internal_font_number f, int c); void end_chararray(PDF pdf); void end_charmode(PDF pdf); void pdf_place_glyph(PDF pdf, internal_font_number f, int c, int ex); diff --git a/source/texk/web2c/luatexdir/pdf/pdfshipout.c b/source/texk/web2c/luatexdir/pdf/pdfshipout.c index 084efc086..4aabe5a00 100644 --- a/source/texk/web2c/luatexdir/pdf/pdfshipout.c +++ b/source/texk/web2c/luatexdir/pdf/pdfshipout.c @@ -196,7 +196,7 @@ void ship_out(PDF pdf, halfword p, shipping_mode_e shipping_mode) cur.v = height(p); synch_pos_with_cur(pdf->posstruct, &refpoint, cur); } else { - /*tex We're shipping out a |/Form|. */ + /*tex We're shipping out a |/Form| or a node font glyph. */ pdf->posstruct->dir = box_dir(p); switch (pdf->posstruct->dir) { case dir_TLT: @@ -217,11 +217,11 @@ void ship_out(PDF pdf, halfword p, shipping_mode_e shipping_mode) switch (pdf->posstruct->dir) { case dir_TLT: pdf->posstruct->pos.h = 0; - pdf->posstruct->pos.v = depth(p); + pdf->posstruct->pos.v = global_shipping_mode == SHIPPING_FORM ? depth(p) : 0; break; case dir_TRT: pdf->posstruct->pos.h = width(p); - pdf->posstruct->pos.v = depth(p); + pdf->posstruct->pos.v = global_shipping_mode == SHIPPING_FORM ? depth(p) : 0; break; case dir_LTL: pdf->posstruct->pos.h = height(p); @@ -233,7 +233,7 @@ void ship_out(PDF pdf, halfword p, shipping_mode_e shipping_mode) break; default: pdf->posstruct->pos.h = 0; - pdf->posstruct->pos.v = depth(p); + pdf->posstruct->pos.v = global_shipping_mode == SHIPPING_FORM ? depth(p) : 0; normal_warning("pdf backend","bad page direction, assuming TLT, case 5"); } } diff --git a/source/texk/web2c/luatexdir/pdf/pdftypes.h b/source/texk/web2c/luatexdir/pdf/pdftypes.h index 67ffcbecb..a2660538b 100644 --- a/source/texk/web2c/luatexdir/pdf/pdftypes.h +++ b/source/texk/web2c/luatexdir/pdf/pdftypes.h @@ -218,11 +218,12 @@ typedef enum { obj_type_bead = 15, /* thread bead objects */ obj_type_beads = 16, /* /B objects (array of bead objects) */ obj_type_objstm = 17, /* /ObjStm objects */ - obj_type_others = 18 /* any other objects (also not linked in any list) */ + obj_type_glyph = 18, /* Type 3 charstring objects */ + obj_type_others = 19 /* any other objects (also not linked in any list) */ } pdf_obj_type; # define HEAD_TAB_MAX 6 /* obj_type_thread */ -# define PDF_OBJ_TYPE_MAX 18 /* obj_type_others */ +# define PDF_OBJ_TYPE_MAX 19 /* obj_type_others */ typedef struct pdf_resource_struct_ { struct avl_table *resources_tree; diff --git a/source/texk/web2c/luatexdir/ptexlib.h b/source/texk/web2c/luatexdir/ptexlib.h index f63f480b0..9de7624bb 100644 --- a/source/texk/web2c/luatexdir/ptexlib.h +++ b/source/texk/web2c/luatexdir/ptexlib.h @@ -313,7 +313,12 @@ extern boolean get_callback(lua_State * L, int i); /* Additions to texmfmp.h for pdfTeX */ /* mark a char in font */ -# define pdf_mark_char(f,c) set_char_used(f,c,true) +# define pdf_mark_char(f,c) do { \ + if(font_format(f) == node_format) { \ + pdf_ship_node_char(static_pdf, f, c); \ + } \ + set_char_used(f,c,true); \ +} while (0) /* test whether a char in font is marked */ # define pdf_char_marked char_used -- 2.23.0
_______________________________________________ dev-luatex mailing list dev-luatex@ntg.nl https://mailman.ntg.nl/mailman/listinfo/dev-luatex