summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/pdf/pdffont.w
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/pdf/pdffont.w')
-rw-r--r--Build/source/texk/web2c/luatexdir/pdf/pdffont.w495
1 files changed, 495 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/pdf/pdffont.w b/Build/source/texk/web2c/luatexdir/pdf/pdffont.w
new file mode 100644
index 00000000000..77b817bb61a
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/pdf/pdffont.w
@@ -0,0 +1,495 @@
+% pdffont.w
+
+% Copyright 2009-2010 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/>.
+
+\def\pdfTeX{pdf\TeX}
+
+@ @c
+static const char _svn_version[] =
+ "$Id: pdffont.w 3571 2010-04-02 13:50:45Z taco $"
+ "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/pdf/pdffont.w $";
+
+#include "ptexlib.h"
+
+@ @c
+#define font_id_text(A) cs_text(font_id_base+(A)) /* a frozen font identifier's name */
+
+int pk_dpi; /* PK pixel density value from \.{texmf.cnf} */
+
+
+@ As \pdfTeX{} should also act as a back-end driver, it needs to support virtual
+fonts too. Information about virtual fonts can be found in the source of some
+\.{DVI}-related programs.
+
+Whenever we want to write out a character in a font to PDF output, we
+should check whether the used character is a virtual or read character.
+The |has_packet()| C macro checks for this condition.
+
+
+@ The following code typesets a character to PDF output
+
+@c
+void output_one_char(PDF pdf, internal_font_number ffi, int c)
+{
+ scaled_whd ci; /* the real width, height and depth of the character */
+ ci = get_charinfo_whd(ffi, c);
+ switch (pdf->posstruct->dir) {
+ case dir_TLT:
+ break;
+ case dir_TRT:
+ pos_left(ci.wd);
+ break;
+ case dir_LTL:
+ pos_down(ci.ht);
+ pos_left(ci.wd);
+ break;
+ case dir_RTT:
+ pos_down(ci.ht);
+ pos_left(ci.wd / 2);
+ break;
+ }
+ if (has_packet(ffi, c)) {
+ assert(pdf->o_mode == OMODE_PDF);
+ do_vf_packet(pdf, ffi, c);
+ } else
+ backend_out[glyph_node] (pdf, ffi, c); /* |pdf_place_glyph(pdf, ffi, c);| */
+}
+
+@ Mark |f| as a used font; set |font_used(f)|, |font_size(f)| and |pdf_font_num(f)|
+@c
+static void pdf_use_font(internal_font_number f, int fontnum)
+{
+ set_font_used(f, true);
+ assert((fontnum > 0) || ((fontnum < 0) && (pdf_font_num(-fontnum) > 0)));
+ set_pdf_font_num(f, fontnum);
+}
+
+@ To set PDF font we need to find out fonts with the same name, because \TeX\
+can load the same font several times for various sizes. For such fonts we
+define only one font resource. The array |pdf_font_num| holds the object
+number of font resource. A negative value of an entry of |pdf_font_num|
+indicates that the corresponding font shares the font resource with the font
+
+@c
+#define same(n,f,k) (n(f) != NULL && n(k) != NULL && strcmp(n(f), n(k)) == 0)
+
+static boolean font_shareable(internal_font_number f, internal_font_number k)
+{
+ int ret = 0;
+ internal_font_number b;
+ /* For some lua-loaded (for instance AFM) fonts, it is normal to have
+ a zero cidregistry, and such fonts do not have a fontmap entry yet
+ at this point, so the test should use the other branch */
+ if (font_cidregistry(f) == NULL && font_cidregistry(k) == NULL &&
+ font_encodingbytes(f) != 2 && font_encodingbytes(k) != 2) {
+ if (font_map(k) != NULL &&
+ font_map(f) != NULL &&
+ (same(font_name, k, f) ||
+ (font_auto_expand(f) &&
+ (b = pdf_font_blink(f)) != 0 && same(font_name, k, b)))) {
+ ret = 1;
+ }
+#ifdef DEBUG
+ printf("\nfont_shareable(%d:%d, %d:%d): => %d\n", f, pdf_font_blink(f),
+ k, pdf_font_blink(k), ret);
+#endif
+ } else {
+ if ((same(font_filename, k, f) && same(font_fullname, k, f))
+ || (font_auto_expand(f)
+ && (b = pdf_font_blink(f)) != 0 && same(font_name, k, b))) {
+ ret = 1;
+ }
+#ifdef DEBUG
+ printf("\nfont_shareable(%d:%s:%s,%d:%s:%s): => %d\n",
+ f, font_filename(f), font_fullname(f),
+ k, font_filename(k), font_fullname(k), ret);
+#endif
+ }
+ return ret;
+}
+
+@ create a font object
+@c
+void pdf_init_font(PDF pdf, internal_font_number f)
+{
+ internal_font_number k, b;
+ fm_entry *fm;
+ int i;
+ assert(!font_used(f));
+
+ /* if |f| is auto expanded then ensure the base font is initialized */
+
+ if (font_auto_expand(f) && ((b = pdf_font_blink(f)) != 0)) {
+ if (!font_used(b))
+ pdf_init_font(pdf, b);
+ set_font_map(f, font_map(b));
+ /* propagate slant and extend from unexpanded base font */
+ set_font_slant(f, font_slant(b));
+ set_font_extend(f, font_extend(b));
+ }
+ /* check whether |f| can share the font object with some |k|: we have 2 cases
+ here: 1) |f| and |k| have the same tfm name (so they have been loaded at
+ different sizes, eg 'cmr10' and 'cmr10 at 11pt'); 2) |f| has been auto
+ expanded from |k|
+ */
+
+ /* take over slant and extend from map entry, if not already set;
+ this should also be the only place where getfontmap() may be called. */
+
+ fm = getfontmap(font_name(f));
+ if (font_map(f) == NULL && fm != NULL) {
+ font_map(f) = fm;
+ if (is_slantset(fm))
+ font_slant(f) = fm->slant;
+ if (is_extendset(fm))
+ font_extend(f) = fm->extend;
+ }
+ i = pdf->head_tab[obj_type_font];
+ while (i != 0) {
+ k = obj_info(pdf, i);
+ if (font_shareable(f, k)) {
+ assert(pdf_font_num(k) != 0);
+ if (pdf_font_num(k) < 0)
+ pdf_use_font(f, pdf_font_num(k));
+ else
+ pdf_use_font(f, -k);
+ return;
+ }
+ i = obj_link(pdf, i);
+ }
+ /* create a new font object for |f| */
+ pdf_create_obj(pdf, obj_type_font, f);
+ pdf_use_font(f, pdf->obj_ptr);
+}
+
+@ set the actual font on PDF page
+@c
+internal_font_number pdf_set_font(PDF pdf, internal_font_number f)
+{
+ int ff; /* for use with |set_ff| */
+ if (!font_used(f))
+ pdf_init_font(pdf, f);
+ /*
+ set |ff| to the tfm number of the base font sharing the font object with |f|;
+ |ff| is either |f| itself (then it is its own base font),
+ or some font with the same tfm name at different size and/or expansion.
+ */
+ ff = pdf_font_num(f) < 0 ? -pdf_font_num(f) : f; /* aka |set_ff(f)| */
+ addto_page_resources(pdf, obj_type_font, ff);
+ return ff;
+}
+
+@ Here come some subroutines to deal with expanded fonts for HZ-algorithm.
+@c
+void copy_expand_params(internal_font_number k, internal_font_number f, int e)
+{ /* set expansion-related parameters for an expanded font |k|, based on the base
+ font |f| and the expansion amount |e| */
+ set_font_expand_ratio(k, e);
+ set_font_step(k, font_step(f));
+ set_font_auto_expand(k, font_auto_expand(f));
+ set_pdf_font_blink(k, f);
+}
+
+@ return 1 == identical
+@c
+static boolean cmp_font_name(int id, char *tt)
+{
+ char *tid;
+ if (!is_valid_font(id))
+ return 0;
+ tid = font_name(id);
+ if (tt == NULL && tid == NULL)
+ return 1;
+ if (tt == NULL || tid == NULL || strcmp(tid, tt) != 0)
+ return 0;
+ return 1;
+}
+
+@ @c
+internal_font_number tfm_lookup(char *s, scaled fs, int e)
+{ /* looks up for a TFM with name |s| loaded at |fs| size; if found then flushes |s| */
+ internal_font_number k;
+ if (fs != 0) {
+ for (k = 1; k <= max_font_id(); k++) {
+ if (cmp_font_name(k, s) && font_size(k) == fs
+ && font_expand_ratio(k) == e) {
+ return k;
+ }
+ }
+ } else {
+ for (k = 1; k <= max_font_id(); k++) {
+ if (cmp_font_name(k, s) && font_expand_ratio(k) == e) {
+ return k;
+ }
+ }
+ }
+ return null_font;
+}
+
+@ @c
+static internal_font_number load_expand_font(internal_font_number f, int e)
+{ /* loads font |f| expanded by |e| thousandths into font memory; |e| is nonzero
+ and is a multiple of |font_step(f)| */
+ internal_font_number k;
+ k = tfm_lookup(font_name(f), font_size(f), e);
+ if (k == null_font) {
+ if (font_auto_expand(f)) {
+ k = auto_expand_font(f, e);
+ font_id_text(k) = font_id_text(f);
+ } else {
+ k = read_font_info(null_cs, font_name(f), font_size(f),
+ font_natural_dir(f));
+ }
+ }
+ copy_expand_params(k, f, e);
+ return k;
+}
+
+@ @c
+static int fix_expand_value(internal_font_number f, int e)
+{ /* return the multiple of |font_step(f)| that is nearest to |e| */
+ int step;
+ int max_expand;
+ boolean neg;
+ if (e == 0)
+ return 0;
+ if (e < 0) {
+ e = -e;
+ neg = true;
+ max_expand = -font_expand_ratio(font_shrink(f));
+ } else {
+ neg = false;
+ max_expand = font_expand_ratio(font_stretch(f));
+ }
+ if (e > max_expand) {
+ e = max_expand;
+ } else {
+ step = font_step(f);
+ if (e % step > 0)
+ e = step * round_xn_over_d(e, 1, step);
+ }
+ if (neg)
+ e = -e;
+ return e;
+}
+
+@ @c
+static internal_font_number get_expand_font(internal_font_number f, int e)
+{ /* look up and create if not found an expanded version of |f|; |f| is an
+ expandable font; |e| is nonzero and is a multiple of |font_step(f)| */
+ internal_font_number k;
+ k = pdf_font_elink(f);
+ while (k != null_font) {
+ if (font_expand_ratio(k) == e)
+ return k;
+ k = pdf_font_elink(k);
+ }
+ k = load_expand_font(f, e);
+ set_pdf_font_elink(k, pdf_font_elink(f));
+ set_pdf_font_elink(f, k);
+ return k;
+}
+
+@ @c
+internal_font_number expand_font(internal_font_number f, int e)
+{ /* looks up for font |f| expanded by |e| thousandths, |e| is an arbitrary value
+ between max stretch and max shrink of |f|; if not found then creates it */
+ if (e == 0)
+ return f;
+ e = fix_expand_value(f, e);
+ if (e == 0)
+ return f;
+ if (pdf_font_elink(f) == null_font)
+ pdf_error("font expansion", "uninitialized pdf_font_elink");
+ return get_expand_font(f, e);
+}
+
+@ @c
+void set_expand_params(internal_font_number f, boolean auto_expand,
+ int stretch_limit, int shrink_limit,
+ int font_step, int expand_ratio)
+{ /* expand a font with given parameters */
+ set_font_step(f, font_step);
+ set_font_auto_expand(f, auto_expand);
+ if (stretch_limit > 0)
+ set_font_stretch(f, get_expand_font(f, stretch_limit));
+ if (shrink_limit > 0)
+ set_font_shrink(f, get_expand_font(f, -shrink_limit));
+ if (expand_ratio != 0)
+ set_font_expand_ratio(f, expand_ratio);
+}
+
+@ @c
+void read_expand_font(void)
+{ /* read font expansion spec and load expanded font */
+ int shrink_limit, stretch_limit, font_step;
+ internal_font_number f;
+ boolean auto_expand;
+ /* read font expansion parameters */
+ scan_font_ident();
+ f = cur_val;
+ if (f == null_font)
+ pdf_error("font expansion", "invalid font identifier");
+ if (pdf_font_blink(f) != null_font)
+ pdf_error("font expansion",
+ "\\pdffontexpand cannot be used this way (the base font has been expanded)");
+ scan_optional_equals();
+ scan_int();
+ stretch_limit = fix_int(cur_val, 0, 1000);
+ scan_int();
+ shrink_limit = fix_int(cur_val, 0, 500);
+ scan_int();
+ font_step = fix_int(cur_val, 0, 100);
+ if (font_step == 0)
+ pdf_error("font expansion", "invalid step");
+ stretch_limit = stretch_limit - stretch_limit % font_step;
+ if (stretch_limit < 0)
+ stretch_limit = 0;
+ shrink_limit = shrink_limit - shrink_limit % font_step;
+ if (shrink_limit < 0)
+ shrink_limit = 0;
+ if ((stretch_limit == 0) && (shrink_limit == 0))
+ pdf_error("font expansion", "invalid limit(s)");
+ auto_expand = false;
+ if (scan_keyword("autoexpand")) {
+ auto_expand = true;
+ /* Scan an optional space */
+ get_x_token();
+ if (cur_cmd != spacer_cmd)
+ back_input();
+ }
+
+ /* check if the font can be expanded */
+ if (font_expand_ratio(f) != 0)
+ pdf_error("font expansion",
+ "this font has been expanded by another font so it cannot be used now");
+ if (font_step(f) != 0) {
+ /* this font has been expanded, ensure the expansion parameters are identical */
+ if (font_step(f) != font_step)
+ pdf_error("font expansion",
+ "font has been expanded with different expansion step");
+
+ if (((font_stretch(f) == null_font) && (stretch_limit != 0)) ||
+ ((font_stretch(f) != null_font)
+ && (font_expand_ratio(font_stretch(f)) != stretch_limit)))
+ pdf_error("font expansion",
+ "font has been expanded with different stretch limit");
+
+ if (((font_shrink(f) == null_font) && (shrink_limit != 0)) ||
+ ((font_shrink(f) != null_font)
+ && (-font_expand_ratio(font_shrink(f)) != shrink_limit)))
+ pdf_error("font expansion",
+ "font has been expanded with different shrink limit");
+
+ if (font_auto_expand(f) != auto_expand)
+ pdf_error("font expansion",
+ "font has been expanded with different auto expansion value");
+ } else {
+ if (font_used(f))
+ pdf_warning("font expansion",
+ "font should be expanded before its first use", true,
+ true);
+ set_expand_params(f, auto_expand, stretch_limit, shrink_limit,
+ font_step, 0);
+ if (font_type(f) == virtual_font_type)
+ vf_expand_local_fonts(f);
+ }
+}
+
+@ @c
+void new_letterspaced_font(small_number a)
+{ /* letter-space a font by creating a virtual font */
+ pointer u; /* user's font identifier */
+ str_number t; /* name for the frozen font identifier */
+ internal_font_number f, k;
+ get_r_token();
+ u = cur_cs;
+ if (u >= hash_base)
+ t = cs_text(u);
+ else
+ t = maketexstring("FONT");
+ define(u, set_font_cmd, null_font);
+ scan_optional_equals();
+ scan_font_ident();
+ k = cur_val;
+ scan_int();
+ f = letter_space_font(u, k, fix_int(cur_val, -1000, 1000));
+ equiv(u) = f;
+ eqtb[font_id_base + f] = eqtb[u];
+ font_id_text(f) = t;
+}
+
+@ @c
+void make_font_copy(small_number a)
+{ /* make a font copy for further use with font expansion */
+ pointer u; /* user's font identifier */
+ str_number t; /* name for the frozen font identifier */
+ internal_font_number f, k;
+ get_r_token();
+ u = cur_cs;
+ if (u >= hash_base)
+ t = cs_text(u);
+ else
+ t = maketexstring("FONT");
+ define(u, set_font_cmd, null_font);
+ scan_optional_equals();
+ scan_font_ident();
+ k = cur_val;
+ f = copy_font_info(k);
+ equiv(u) = f;
+ eqtb[font_id_base + f] = eqtb[u];
+ font_id_text(f) = t;
+}
+
+@ @c
+void pdf_include_chars(PDF pdf)
+{
+ str_number s;
+ unsigned char *k, *j; /* running index */
+ internal_font_number f;
+ scan_font_ident();
+ f = cur_val;
+ if (f == null_font)
+ pdf_error("font", "invalid font identifier");
+ pdf_check_vf(cur_val);
+ if (!font_used(f))
+ pdf_init_font(pdf, f);
+ scan_pdf_ext_toks();
+ s = tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ j = str_string(s) + str_length(s);
+ for (k = str_string(s); k < j; k++) {
+ pdf_mark_char(f, *k);
+ }
+ flush_str(s);
+}
+
+@ @c
+void glyph_to_unicode(void)
+{
+ str_number s1, s2;
+ scan_pdf_ext_toks();
+ s1 = tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ scan_pdf_ext_toks();
+ s2 = tokens_to_string(def_ref);
+ delete_token_ref(def_ref);
+ def_tounicode(s1, s2);
+ flush_str(s2);
+ flush_str(s1);
+}