summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/pdf/pdfglyph.c
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-02-25 19:22:25 +0000
committerKarl Berry <karl@freefriends.org>2021-02-25 19:22:25 +0000
commitad547a6b5986815fda458221149728d9d9ab1d87 (patch)
tree16296910eb3eca724371474ea9aea3994dc69614 /Build/source/texk/web2c/luatexdir/pdf/pdfglyph.c
parent947b43de3dd21d58ccc2ffadefc4441ea1c2a813 (diff)
restore Build,TODO from r57911
git-svn-id: svn://tug.org/texlive/trunk@57915 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/pdf/pdfglyph.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/pdf/pdfglyph.c289
1 files changed, 289 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/pdf/pdfglyph.c b/Build/source/texk/web2c/luatexdir/pdf/pdfglyph.c
new file mode 100644
index 00000000000..c7cf0439212
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/pdf/pdfglyph.c
@@ -0,0 +1,289 @@
+/*
+
+Copyright 2009-2011 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/>.
+
+*/
+
+#include "ptexlib.h"
+#include "pdf/pdfpage.h"
+
+/*tex
+
+ The |e_tj| step must be 3 because movements in |[]TJ| are in fontsize/$10^3$
+ units.
+
+*/
+
+#define e_tj 3
+
+/*tex
+
+ Use exactly this formula also for calculating the |/Width| array values.
+
+*/
+
+static int64_t pdf_char_width(pdfstructure * p, internal_font_number f, int i)
+{
+ return i64round((double) char_width(f, i) / font_size(f) * ten_pow[e_tj + p->cw.e]);
+}
+
+void pdf_print_charwidth(PDF pdf, internal_font_number f, int i)
+{
+ pdffloat cw;
+ pdfstructure *p = pdf->pstruct;
+ cw.m = pdf_char_width(p, f, i);
+ cw.e = p->cw.e;
+ print_pdffloat(pdf, cw);
+}
+
+static void setup_fontparameters(PDF pdf, internal_font_number f, int ex_glyph)
+{
+ float slant, extend, squeeze, expand, scale = 1.0;
+ float u = 1.0;
+ pdfstructure *p = pdf->pstruct;
+ if ((font_format(f) == opentype_format || (font_format(f) == type1_format && font_encodingbytes(f) == 2)) && font_units_per_em(f) > 0)
+ u = font_units_per_em(f) / 1000.0;
+ pdf->f_cur = f;
+ p->f_pdf = pdf_set_font(pdf, f);
+ p->fs.m = i64round(font_size(f) / u / by_one_bp * ten_pow[p->fs.e]);
+ slant = font_slant(f) / 1000.0;
+ extend = font_extend(f) / 1000.0;
+ squeeze = font_squeeze(f) / 1000.0;
+ expand = 1.0 + (ex_glyph/1) / 1000.0;
+ /*tex The |-1| makes less corrections inside |[]TJ|: */
+ p->tj_delta.e = p->cw.e - 1;
+ /*tex There is no need to be more precise than \TEX\ (1sp). */
+ while (p->tj_delta.e > 0 && (double) font_size(f) / ten_pow[p->tj_delta.e + e_tj] < 0.5) {
+ /*tex This happens for very tiny fonts. */
+ p->tj_delta.e--;
+ }
+ p->tm[0].m = i64round(scale * expand * extend * ten_pow[p->tm[0].e]);
+ p->tm[2].m = i64round(slant * ten_pow[p->tm[2].e]);
+ p->tm[3].m = i64round(scale * squeeze * ten_pow[p->tm[3].e]);
+ p->k2 = ten_pow[e_tj + p->cw.e] * scale / (ten_pow[p->pdf.h.e] * pdf2double(p->fs) * pdf2double(p->tm[0]));
+ /*tex We keep track of the state of ex. */
+ p->cur_ex = ex_glyph ;
+ p->need_width = font_width(f);
+ p->need_mode = font_mode(f);
+}
+
+static void set_font(PDF pdf)
+{
+ pdfstructure *p = pdf->pstruct;
+
+ if (p->need_width != 0) {
+ pdf_printf(pdf, "%0.3f w\n",((7227.0/7200.0)/1000.0) * p->need_width );
+ p->done_width = 1;
+ } else if (p->done_width) {
+ pdf_puts(pdf, "0 w\n");
+ p->done_width = 0;
+ }
+ if (p->need_mode != 0) {
+ pdf_printf(pdf, "%d Tr\n", (int) p->need_mode);
+ p->done_mode = 1;
+ } else if (p->done_mode) {
+ pdf_puts(pdf, "0 Tr\n");
+ p->done_mode = 0;
+ }
+ pdf_printf(pdf, "/F%d", (int) p->f_pdf);
+ pdf_print_resname_prefix(pdf);
+ pdf_out(pdf, ' ');
+ print_pdffloat(pdf, p->fs);
+ pdf_puts(pdf, " Tf\n");
+ p->f_pdf_cur = p->f_pdf;
+ p->fs_cur.m = p->fs.m;
+ p->need_tf = false;
+ /*tex Always follow |Tf| by |Tm|: */
+ p->need_tm = true;
+}
+
+static void set_textmatrix(PDF pdf, scaledpos pos)
+{
+ boolean move;
+ pdfstructure *p = pdf->pstruct;
+ if (!is_textmode(p))
+ normal_error("pdf backend","text mode expected in set_textmatrix");
+ move = calc_pdfpos(p, pos);
+ if (p->need_tm || move) {
+ print_pdf_matrix(pdf, p->tm);
+ pdf_puts(pdf, " Tm ");
+ /*tex |Tm| replaces */
+ p->pdf.h.m = p->pdf_bt_pos.h.m + p->tm[4].m;
+ p->pdf.v.m = p->pdf_bt_pos.v.m + p->tm[5].m;
+ p->need_tm = false;
+ }
+ p->tm0_cur.m = p->tm[0].m;
+}
+
+/*tex
+
+ Print out a character to PDF buffer; the character will be printed in octal
+ form in the following cases: chars <= 32, backslash (92), left parenthesis
+ (40), and right parenthesis (41).
+
+*/
+
+static void pdf_print_char(PDF pdf, int c)
+{
+ if (c > 255) {
+ return;
+ } else if (c <= 32 || c == '\\' || c == '(' || c == ')' || c > 127) {
+ pdf_room(pdf, 4);
+ pdf_quick_out(pdf, '\\');
+ pdf_quick_out(pdf, (unsigned char) ('0' + ((c >> 6) & 0x3)));
+ pdf_quick_out(pdf, (unsigned char) ('0' + ((c >> 3) & 0x7)));
+ pdf_quick_out(pdf, (unsigned char) ('0' + (c & 0x7)));
+ } else
+ pdf_out(pdf, c);
+}
+
+static void pdf_print_wide_char(PDF pdf, int c)
+{
+ char hex[5];
+ snprintf(hex, 5, "%04X", c);
+ pdf_out_block(pdf, (const char *) hex, 4);
+}
+
+static void begin_charmode(PDF pdf, internal_font_number f, pdfstructure * p)
+{
+ if (!is_chararraymode(p))
+ normal_error("pdf backend","char array mode expected in begin_char_mode");
+ if (font_encodingbytes(f) == 2) {
+ p->ishex = 1;
+ pdf_out(pdf, '<');
+ } else {
+ p->ishex = 0;
+ pdf_out(pdf, '(');
+ }
+ p->mode = PMODE_CHAR;
+}
+
+void end_charmode(PDF pdf)
+{
+ pdfstructure *p = pdf->pstruct;
+ if (!is_charmode(p))
+ normal_error("pdf backend","char mode expected in end_char_mode");
+ if (p->ishex == 1) {
+ p->ishex = 0;
+ pdf_out(pdf, '>');
+ } else {
+ pdf_out(pdf, ')');
+ }
+ p->mode = PMODE_CHARARRAY;
+}
+
+static void begin_chararray(PDF pdf)
+{
+ pdfstructure *p = pdf->pstruct;
+ if (!is_textmode(p))
+ normal_error("pdf backend","text mode expected in begin_char_array");
+ p->pdf_tj_pos = p->pdf;
+ p->cw.m = 0;
+ pdf_out(pdf, '[');
+ p->mode = PMODE_CHARARRAY;
+}
+
+void end_chararray(PDF pdf)
+{
+ pdfstructure *p = pdf->pstruct;
+ if (!is_chararraymode(p))
+ normal_error("pdf backend","char array mode expected in end_char_array");
+ pdf_puts(pdf, "]TJ\n");
+ p->pdf = p->pdf_tj_pos;
+ p->mode = PMODE_TEXT;
+}
+
+/*tex
+
+ We need to adapt the tm when a font changes. A change can be a change in id
+ (frontend) or pdf reference (backend, as we share font resources). At such a
+ change we also need to adapt to the slant and extend. Initially we also need
+ to take the exfactor of a glyph into account. When the font is unchanged, we
+ still need to check each glyph for a change in exfactor. We store the current
+ one on the state record so that we can minimize testing.
+
+*/
+
+void pdf_place_glyph(PDF pdf, internal_font_number f, int c, int ex)
+{
+ boolean move;
+ pdfstructure *p = pdf->pstruct;
+ scaledpos pos = pdf->posstruct->pos;
+ /*tex
+
+ This is already done:
+
+ \startyping
+ if (!char_exists(f, c)) {
+ return;
+ }
+ \stoptyping
+
+ */
+ if (font_writingmode(f) == vertical_writingmode) {
+ if (p->wmode != WMODE_V) {
+ p->wmode = WMODE_V;
+ p->need_tm = true;
+ }
+ } else {
+ if (p->wmode != WMODE_H) {
+ p->wmode = WMODE_H;
+ p->need_tm = true;
+ }
+ }
+ if (p->need_tf || f != pdf->f_cur || p->f_pdf != p->f_pdf_cur || p->fs.m != p->fs_cur.m || is_pagemode(p)) {
+ pdf_goto_textmode(pdf);
+ setup_fontparameters(pdf, f, ex);
+ set_font(pdf);
+ } else if (p->tm0_cur.m != p->tm[0].m || p->cur_ex != ex) {
+ setup_fontparameters(pdf, f, ex);
+ p->need_tm = true;
+ }
+ /*tex All movements within text or chararray or char mode: */
+ move = calc_pdfpos(p, pos);
+ if (move || p->need_tm) {
+ if (p->need_tm
+ || (p->wmode == WMODE_H && (p->pdf_bt_pos.v.m + p->tm[5].m) != p->pdf.v.m)
+ || (p->wmode == WMODE_V && (p->pdf_bt_pos.h.m + p->tm[4].m) != p->pdf.h.m)
+ || abs(p->tj_delta.m) >= 1000000) {
+ pdf_goto_textmode(pdf);
+ set_textmatrix(pdf, pos);
+ begin_chararray(pdf);
+ /*tex For fine adjustment: */
+ move = calc_pdfpos(p, pos);
+ }
+ if (move) {
+ if (is_charmode(p))
+ end_charmode(pdf);
+ print_pdffloat(pdf, p->tj_delta);
+ p->cw.m -= p->tj_delta.m * ten_pow[p->cw.e - p->tj_delta.e];
+ }
+ }
+ /*tex Glyph output: */
+ if (is_chararraymode(p))
+ begin_charmode(pdf, f, p);
+ else if (!is_charmode(p))
+ normal_error("pdf backend","char (array) mode expected in place_glyph");
+ pdf_mark_char(f, c);
+ if (font_encodingbytes(f) == 2)
+ pdf_print_wide_char(pdf, char_index(f, c));
+ else
+ pdf_print_char(pdf, c);
+ /*tex Also known as |adv_char_width()|: */
+ p->cw.m += pdf_char_width(p, p->f_pdf, c);
+}