1% pdffont.w
2%
3% Copyright 2009-2014 Taco Hoekwater <taco@@luatex.org>
4%
5% This file is part of LuaTeX.
6%
7% LuaTeX is free software; you can redistribute it and/or modify it under
8% the terms of the GNU General Public License as published by the Free
9% Software Foundation; either version 2 of the License, or (at your
10% option) any later version.
11%
12% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14% FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15% License for more details.
16%
17% You should have received a copy of the GNU General Public License along
18% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
19
20\def\pdfTeX{pdf\TeX}
21
22@ @c
23
24
25#include "ptexlib.h"
26
27@ @c
28#define font_id_text(A) cs_text(font_id_base+(A))       /* a frozen font identifier's name */
29
30int pk_dpi;                     /* PK pixel density value from \.{texmf.cnf} */
31
32
33@ As \pdfTeX{} should also act as a back-end driver, it needs to support virtual
34fonts too. Information about virtual fonts can be found in the source of some
35\.{DVI}-related programs.
36
37Whenever we want to write out a character in a font to PDF output, we
38should check whether the used character is a virtual or real character.
39The |has_packet()| C macro checks for this condition.
40
41
42@ The following code typesets a character to PDF output
43
44@c
45scaled_whd output_one_char(PDF pdf, halfword p)
46{
47    scaled_whd ci;              /* the real width, height and depth of the character */
48    internal_font_number f = font(p);
49    int c = character(p);
50    int ex_glyph = ex_glyph(p)/1000;
51    ci = get_charinfo_whd(f, c);
52    if (!(char_exists(f,c))) {
53        char_warning(f,c);
54        return ci;
55    }
56    //ci.wd = round_xn_over_d(ci.wd, 1000 + ex_glyph, 1000);
57    ci.wd = ext_xn_over_d(ci.wd, 1000000 + ex_glyph(p), 1000000);
58    switch (pdf->posstruct->dir) {
59    case dir_TLT:
60        break;
61    case dir_TRT:
62        pos_left(ci.wd);
63        break;
64    case dir_LTL:
65        pos_down(ci.ht);
66        pos_left(ci.wd);
67        break;
68    case dir_RTT:
69        pos_down(ci.ht);
70        pos_left(ci.wd / 2);
71        break;
72    default:
73        assert(0);
74    }
75    if (has_packet(f, c)) {
76        do_vf_packet(pdf, f, c, ex_glyph);
77    } else
78        backend_out[glyph_node] (pdf, f, c, ex_glyph);  /* |pdf_place_glyph(pdf, f, c, ex_glyph);| */
79    return ci;
80}
81
82@ Mark |f| as a used font; set |font_used(f)|, |font_size(f)| and |pdf_font_num(f)|
83@c
84static void pdf_use_font(internal_font_number f, int fontnum)
85{
86    set_font_used(f, true);
87    assert((fontnum > 0) || ((fontnum < 0) && (pdf_font_num(-fontnum) > 0)));
88    set_pdf_font_num(f, fontnum);
89}
90
91@ To set PDF font we need to find out fonts with the same name, because \TeX\
92can load the same font several times for various sizes. For such fonts we
93define only one font resource. The array |pdf_font_num| holds the object
94number of font resource. A negative value of an entry of |pdf_font_num|
95indicates that the corresponding font shares the font resource with the font
96
97@c
98#define same(n,f,k) (n(f) != NULL && n(k) != NULL && strcmp(n(f), n(k)) == 0)
99
100static boolean font_shareable(internal_font_number f, internal_font_number k)
101{
102    int ret = 0;
103    /* For some lua-loaded (for instance AFM) fonts, it is normal to have
104       a zero cidregistry,  and such fonts do not have a fontmap entry yet
105       at this point, so the test should use the other branch  */
106    if (font_cidregistry(f) == NULL && font_cidregistry(k) == NULL &&
107        font_encodingbytes(f) != 2 && font_encodingbytes(k) != 2) {
108        if (font_map(k) != NULL &&
109            font_map(f) != NULL && (same(font_name, k, f))) {
110            ret = 1;
111        }
112    } else {
113        if ((same(font_filename, k, f) && same(font_fullname, k, f))) {
114            ret = 1;
115        }
116#ifdef DEBUG
117        printf("\nfont_shareable(%d:%s:%s,%d:%s:%s): => %d\n",
118               f, font_filename(f), font_fullname(f),
119               k, font_filename(k), font_fullname(k), ret);
120#endif
121    }
122    return ret;
123}
124
125@ create a font object
126@c
127void pdf_init_font(PDF pdf, internal_font_number f)
128{
129    internal_font_number k/*, b*/;
130    fm_entry *fm;
131    int i, l;
132    assert(!font_used(f));
133
134    ///* if |f| is auto expanded then ensure the base font is initialized */
135    //
136    //    if (font_auto_expand(f) && ((b = pdf_font_blink(f)) != null_font)) {
137    //    if (!font_used(b))
138    //        pdf_init_font(pdf, b);
139    //    set_font_map(f, font_map(b));
140    //    /* propagate slant and extend from unexpanded base font */
141    //    set_font_slant(f, font_slant(b));
142    //    set_font_extend(f, font_extend(b));
143    //}
144    /* check whether |f| can share the font object with some |k|: we have 2 cases
145       here: 1) |f| and |k| have the same tfm name (so they have been loaded at
146       different sizes, eg 'cmr10' and 'cmr10 at 11pt'); 2) |f| has been auto
147       expanded from |k|
148     */
149
150    /* take over slant and extend from map entry, if not already set;
151       this should also be the only place where getfontmap() may be called. */
152
153    fm = getfontmap(font_name(f));
154    if (font_map(f) == NULL && fm != NULL) {
155        font_map(f) = fm;
156        if (is_slantset(fm))
157            font_slant(f) = fm->slant;
158        if (is_extendset(fm))
159            font_extend(f) = fm->extend;
160    }
161    i = pdf->head_tab[obj_type_font];
162    while (i != 0) {
163        k = obj_info(pdf, i);
164        if (font_shareable(f, k)) {
165            assert(pdf_font_num(k) != 0);
166            if (pdf_font_num(k) < 0)
167                pdf_use_font(f, pdf_font_num(k));
168            else
169                pdf_use_font(f, -k);
170            return;
171        }
172        i = obj_link(pdf, i);
173    }
174    /* create a new font object for |f| */
175    l = pdf_create_obj(pdf, obj_type_font, f);
176    pdf_use_font(f, l);
177}
178
179@ set the actual font on PDF page
180@c
181internal_font_number pdf_set_font(PDF pdf, internal_font_number f)
182{
183    int ff;                     /* for use with |set_ff| */
184    if (!font_used(f))
185        pdf_init_font(pdf, f);
186    /*
187       set |ff| to the tfm number of the base font sharing the font object with |f|;
188       |ff| is either |f| itself (then it is its own base font),
189       or some font with the same tfm name at different size and/or expansion.
190     */
191    ff = pdf_font_num(f) < 0 ? -pdf_font_num(f) : f;    /* aka |set_ff(f)| */
192    assert(pdf_font_num(ff) > 0);       /* base font object number */
193    addto_page_resources(pdf, obj_type_font, pdf_font_num(ff));
194    return ff;
195}
196
197@ Here come some subroutines to deal with expanded fonts for HZ-algorithm.
198return 1 == identical
199@c
200static boolean cmp_font_name(int id, char *tt)
201{
202    char *tid;
203    if (!is_valid_font(id))
204        return 0;
205    tid = font_name(id);
206    if (tt == NULL && tid == NULL)
207        return 1;
208    if (tt == NULL || tid == NULL || strcmp(tid, tt) != 0)
209        return 0;
210    return 1;
211}
212
213@ @c
214internal_font_number tfm_lookup(char *s, scaled fs)
215{                               /* looks up for a TFM with name |s| loaded at |fs| size; if found then flushes |s| */
216    internal_font_number k;
217    if (fs != 0) {
218        for (k = 1; k <= max_font_id(); k++) {
219            if (cmp_font_name(k, s) && font_size(k) == fs) {
220                return k;
221            }
222        }
223    } else {
224        for (k = 1; k <= max_font_id(); k++) {
225            if (cmp_font_name(k, s)) {
226                return k;
227            }
228        }
229    }
230    return null_font;
231}
232
233@ @c
234int fix_expand_value(internal_font_number f, int e)
235{                               /* return the multiple of |font_step(f)| that is nearest to |e| */
236    int step;
237    int max_expand;
238    boolean neg;
239    if (e == 0)
240        return 0;
241    if (e < 0) {
242        e = -e;
243        neg = true;
244        max_expand = font_max_shrink(f);
245    } else {
246        neg = false;
247        max_expand = font_max_stretch(f);
248    }
249    if (e > max_expand) {
250        e = max_expand;
251    } else {
252        step = font_step(f);
253        if (e % step > 0)
254            e = step * round_xn_over_d(e, 1, step);
255    }
256    if (neg)
257        e = -e;
258    return e;
259}
260
261@ @c
262void set_expand_params(internal_font_number f, boolean auto_expand,
263                       int stretch_limit, int shrink_limit, int font_step)
264{                               /* expand a font with given parameters */
265    set_font_step(f, font_step);
266    set_font_auto_expand(f, auto_expand);
267    set_font_max_shrink(f, shrink_limit);
268    set_font_max_stretch(f, stretch_limit);
269}
270
271@ @c
272void read_expand_font(void)
273{                               /* read font expansion spec and load expanded font */
274    int shrink_limit, stretch_limit, font_step;
275    internal_font_number f;
276    boolean auto_expand;
277    /* read font expansion parameters */
278    scan_font_ident();
279    f = cur_val;
280    if (f == null_font)
281        pdf_error("font expansion", "invalid font identifier");
282    //if (pdf_font_blink(f) != null_font)
283    //    pdf_error("font expansion",
284    //              "\\pdffontexpand cannot be used this way (the base font has been expanded)");
285    scan_optional_equals();
286    scan_int();
287    stretch_limit = fix_int(cur_val, 0, 1000);
288    scan_int();
289    shrink_limit = fix_int(cur_val, 0, 500);
290    scan_int();
291    font_step = fix_int(cur_val, 0, 100);
292    if (font_step == 0)
293        pdf_error("font expansion", "invalid step");
294    stretch_limit = stretch_limit - stretch_limit % font_step;
295    if (stretch_limit < 0)
296        stretch_limit = 0;
297    shrink_limit = shrink_limit - shrink_limit % font_step;
298    if (shrink_limit < 0)
299        shrink_limit = 0;
300    if ((stretch_limit == 0) && (shrink_limit == 0))
301        pdf_error("font expansion", "invalid limit(s)");
302    auto_expand = false;
303    if (scan_keyword("autoexpand")) {
304        auto_expand = true;
305        /* Scan an optional space */
306        get_x_token();
307        if (cur_cmd != spacer_cmd)
308            back_input();
309    }
310
311    if (font_step(f) != 0) {
312        /* this font has been expanded, ensure the expansion parameters are identical */
313        if (font_step(f) != font_step)
314            pdf_error("font expansion",
315                      "font has been expanded with different expansion step");
316
317        if (((font_max_stretch(f) == 0) && (stretch_limit != 0)) ||
318            ((font_max_stretch(f) > 0)
319             && (font_max_stretch(f) != stretch_limit)))
320            pdf_error("font expansion",
321                      "font has been expanded with different stretch limit");
322
323        if (((font_max_shrink(f) == 0) && (shrink_limit != 0)) ||
324            ((font_max_shrink(f) > 0)
325             && (font_max_shrink(f) != shrink_limit)))
326            pdf_error("font expansion",
327                      "font has been expanded with different shrink limit");
328
329        if (font_auto_expand(f) != auto_expand)
330            pdf_error("font expansion",
331                      "font has been expanded with different auto expansion value");
332    } else {
333        if (font_used(f))
334            pdf_warning("font expansion",
335                        "font should be expanded before its first use", true,
336                        true);
337        set_expand_params(f, auto_expand, stretch_limit, shrink_limit,
338                          font_step);
339    }
340}
341
342@ @c
343void new_letterspaced_font(small_number a)
344{                               /* letter-space a font by creating a virtual font */
345    pointer u;                  /* user's font identifier */
346    str_number t;               /* name for the frozen font identifier */
347    internal_font_number f, k;
348    boolean nolig = false;
349    get_r_token();
350    u = cur_cs;
351    if (u >= hash_base)
352        t = cs_text(u);
353    else
354        t = maketexstring("FONT");
355    define(u, set_font_cmd, null_font);
356    scan_optional_equals();
357    scan_font_ident();
358    k = cur_val;
359    scan_int();
360    if (scan_keyword("nolig"))
361       nolig=true;
362    f = letter_space_font(k, fix_int(cur_val, -1000, 1000), nolig);
363    equiv(u) = f;
364    eqtb[font_id_base + f] = eqtb[u];
365    font_id_text(f) = t;
366}
367
368@ @c
369void make_font_copy(small_number a)
370{                               /* make a font copy for further use with font expansion */
371    pointer u;                  /* user's font identifier */
372    str_number t;               /* name for the frozen font identifier */
373    internal_font_number f, k;
374    get_r_token();
375    u = cur_cs;
376    if (u >= hash_base)
377        t = cs_text(u);
378    else
379        t = maketexstring("FONT");
380    define(u, set_font_cmd, null_font);
381    scan_optional_equals();
382    scan_font_ident();
383    k = cur_val;
384    f = copy_font_info(k);
385    equiv(u) = f;
386    eqtb[font_id_base + f] = eqtb[u];
387    font_id_text(f) = t;
388}
389
390@ @c
391void pdf_include_chars(PDF pdf)
392{
393    str_number s;
394    unsigned char *k, *j;       /* running index */
395    internal_font_number f;
396    scan_font_ident();
397    f = cur_val;
398    if (f == null_font)
399        pdf_error("font", "invalid font identifier");
400    pdf_check_vf(cur_val);
401    if (!font_used(f))
402        pdf_init_font(pdf, f);
403    scan_pdf_ext_toks();
404    s = tokens_to_string(def_ref);
405    delete_token_ref(def_ref);
406    j = str_string(s) + str_length(s);
407    for (k = str_string(s); k < j; k++) {
408        pdf_mark_char(f, *k);
409    }
410    flush_str(s);
411}
412
413@ @c
414void glyph_to_unicode(void)
415{
416    str_number s1, s2;
417    scan_pdf_ext_toks();
418    s1 = tokens_to_string(def_ref);
419    delete_token_ref(def_ref);
420    scan_pdf_ext_toks();
421    s2 = tokens_to_string(def_ref);
422    delete_token_ref(def_ref);
423    def_tounicode(s1, s2);
424    flush_str(s2);
425    flush_str(s1);
426}
427