diff options
Diffstat (limited to 'Build/source/texk/lcdf-typetools/lcdf-typetools-src/libefont/t1csgen.cc')
-rw-r--r-- | Build/source/texk/lcdf-typetools/lcdf-typetools-src/libefont/t1csgen.cc | 636 |
1 files changed, 0 insertions, 636 deletions
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-src/libefont/t1csgen.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-src/libefont/t1csgen.cc deleted file mode 100644 index 7c970374fe2..00000000000 --- a/Build/source/texk/lcdf-typetools/lcdf-typetools-src/libefont/t1csgen.cc +++ /dev/null @@ -1,636 +0,0 @@ -// -*- related-file-name: "../include/efont/t1csgen.hh" -*- - -/* t1csgen.{cc,hh} -- Type 1 charstring generation - * - * Copyright (c) 1998-2019 Eddie Kohler - * - * This program 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. This program 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 General - * Public License for more details. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <efont/t1csgen.hh> -#include <efont/t1font.hh> -#include <efont/t1item.hh> -#include <math.h> -namespace Efont { - -static const char * const command_desc[] = { - 0, 0, 0, 0, "y", - "xy", "x", "y", "xyxyxy", 0, - - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - - 0, "xy", "x", 0, 0, - 0, 0, 0, 0, 0, - - "yxyx", "xxyy", 0, 0, 0, - 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, - "XY", 0, 0, 0, 0 -}; - -Type1CharstringGen::Type1CharstringGen(int precision) -{ - if (precision >= 1 && precision <= 107) - _precision = precision; - else - _precision = 5; - _f_precision = _precision; - clear(); -} - -void -Type1CharstringGen::clear() -{ - _ncs.clear(); - _true = _false = Point(0, 0); - _state = S_INITIAL; -} - - -void -Type1CharstringGen::gen_rational(int big_val, int divisor) -{ - int frac = big_val % divisor; - int val = (frac == 0 ? big_val / divisor : big_val); - - if (val >= -107 && val <= 107) - _ncs.append((char)(val + 139)); - - else if (val >= -1131 && val <= 1131) { - int base = val < 0 ? 251 : 247; - if (val < 0) val = -val; - val -= 108; - int w = val % 256; - val = (val - w) / 256; - _ncs.append((char)(val + base)); - _ncs.append((char)w); - - } else { - _ncs.append('\377'); - long l = val; - _ncs.append((char)((l >> 24) & 0xFF)); - _ncs.append((char)((l >> 16) & 0xFF)); - _ncs.append((char)((l >> 8) & 0xFF)); - _ncs.append((char)((l >> 0) & 0xFF)); - } - - if (frac != 0) { - _ncs.append((char)(divisor + 139)); - _ncs.append((char)Charstring::cEscape); - _ncs.append((char)(Charstring::cDiv - Charstring::cEscapeDelta)); - } -} - -void -Type1CharstringGen::gen_number(double float_val, int kind) -{ - switch (kind) { - case 'x': - _true.x += float_val; - float_val = _true.x - _false.x; - break; - case 'y': - _true.y += float_val; - float_val = _true.y - _false.y; - break; - case 'X': - _true.x = float_val; - break; - case 'Y': - _true.y = float_val; - break; - } - - // 30.Jul.2003 - Avoid rounding differences between platforms with the - // extra 0.00001. - int big_val = (int)floor(float_val * _f_precision + 0.50001); - - gen_rational(big_val, _precision); - - float_val = big_val / _f_precision; - switch (kind) { - case 'x': - _false.x += float_val; - break; - case 'y': - _false.y += float_val; - break; - case 'X': - _false.x = float_val; - break; - case 'Y': - _false.y = float_val; - break; - } -} - - -void -Type1CharstringGen::gen_command(int command) -{ - if (command >= Charstring::cEscapeDelta) { - _ncs.append((char)Charstring::cEscape); - _ncs.append((char)(command - Charstring::cEscapeDelta)); - if (command != Charstring::cSbw) - _state = S_GEN; - } else { - _ncs.append((char)command); - if (command > Charstring::cVmoveto && command != Charstring::cHsbw) - _state = S_GEN; - } -} - -bool -Type1CharstringGen::gen_stem3_stack(CharstringInterp &interp) -{ - // special handling to ensure rounding doesn't generate an invalid stem3 - // hint - if (interp.size() < 6) - return false; - - // sort hints - int i0, i1, i2; - if (interp.at(0) > interp.at(2)) - i0 = 2, i1 = 0; - else - i0 = 0, i1 = 2; - if (interp.at(4) < interp.at(i0)) - i2 = i1, i1 = i0, i0 = 4; - else if (interp.at(4) < interp.at(i1)) - i2 = i1, i1 = 4; - else - i2 = 4; - - // check constraints. count "almost equal" as equal - double stemw0 = interp.at(i0+1), stemw2 = interp.at(i2+1); - if ((int)(1024*(stemw0 - stemw2) + .5) != 0) - return false; - - double c0 = interp.at(i0) + interp.at(i0+1)/2; - double c1 = interp.at(i1) + interp.at(i1+1)/2; - double c2 = interp.at(i2) + interp.at(i2+1)/2; - if ((int)(1024*((c1 - c0) - (c2 - c1)) + .5) != 0) - return false; - - // if all constraints are satisfied now, make sure they are also satisfied - // after rounding - int big_v0 = (int)floor(interp.at(i0) * _f_precision + 0.50001); - int big_v2 = (int)floor(interp.at(i2) * _f_precision + 0.50001); - int big_stemw0 = (int)floor(stemw0 * _f_precision + 0.50001); - int big_stemw1 = (int)floor(interp.at(i1+1) * _f_precision + 0.50001); - - int big_v1_times2 = big_v0 + big_v2 + big_stemw0 - big_stemw1; - - gen_rational(big_v0, _precision); - gen_rational(big_stemw0, _precision); - if (big_v1_times2 % 2) - gen_rational(big_v1_times2, 2 * _precision); - else - gen_rational(big_v1_times2 / 2, _precision); - gen_rational(big_stemw1, _precision); - gen_rational(big_v2, _precision); - gen_rational(big_stemw0, _precision); - - interp.clear(); - return true; -} - -void -Type1CharstringGen::gen_stack(CharstringInterp &interp, int for_cmd) -{ - const char *str = ((unsigned)for_cmd <= Charstring::cLastCommand ? command_desc[for_cmd] : (const char *)0); - if ((for_cmd == Charstring::cHstem3 || for_cmd == Charstring::cVstem3) - && gen_stem3_stack(interp)) - return; - - int i; - for (i = 0; str && *str && i < interp.size(); i++, str++) - gen_number(interp.at(i), *str); - for (; i < interp.size(); i++) - gen_number(interp.at(i)); - interp.clear(); -} - -void -Type1CharstringGen::gen_moveto(const Point &p, bool closepath, bool always) -{ - // make sure we generate some moveto on the first command - - Point d = p - _true; - int big_dx = (int)floor(d.x * _f_precision + 0.50001); - int big_dy = (int)floor(d.y * _f_precision + 0.50001); - - if (big_dx == 0 && big_dy == 0 && _state != S_INITIAL && !always) - /* do nothing */; - else { - if (closepath) - gen_command(Charstring::cClosepath); - if (big_dy == 0) { - gen_number(d.x, 'x'); - gen_command(Charstring::cHmoveto); - } else if (big_dx == 0) { - gen_number(d.y, 'y'); - gen_command(Charstring::cVmoveto); - } else { - gen_number(d.x, 'x'); - gen_number(d.y, 'y'); - gen_command(Charstring::cRmoveto); - } - } - - _true = p; -} - -void -Type1CharstringGen::append_charstring(const String &s) -{ - _ncs << s; -} - -Type1Charstring * -Type1CharstringGen::output() -{ - return new Type1Charstring(take_string()); -} - -void -Type1CharstringGen::output(Type1Charstring &cs) -{ - cs.assign(take_string()); -} - -String -Type1CharstringGen::callsubr_string(int subr) -{ - Type1CharstringGen csg; - csg.gen_number(subr); - csg.gen_command(Charstring::cCallsubr); - return csg._ncs.take_string(); -} - - -/***** - * Type1CharstringGenInterp - **/ - -Type1CharstringGenInterp::Type1CharstringGenInterp(int precision) - : _csgen(precision), _hint_csgen(precision), - _direct_hr(false), _hr_storage(0), - _max_flex_height(0), - _had_flex(false), _had_bad_flex(false), _had_hr(false) -{ -} - -void -Type1CharstringGenInterp::set_hint_replacement_storage(Type1Font *font) -{ - _hr_storage = font; - _hr_firstsubr = font->nsubrs(); -} - - -// generating charstring commands - -inline void -Type1CharstringGenInterp::gen_number(double n, int what) -{ - _csgen.gen_number(n, what); -} - -inline void -Type1CharstringGenInterp::gen_command(int what) -{ - _csgen.gen_command(what); -} - -void -Type1CharstringGenInterp::gen_sbw(bool hints_follow) -{ - if (!hints_follow && nhints()) - act_hintmask(Cs::cHintmask, 0, nhints()); - else if (left_sidebearing().y == 0 && _width.y == 0) { - gen_number(left_sidebearing().x, 'X'); - gen_number(_width.x); - gen_command(Cs::cHsbw); - } else { - gen_number(left_sidebearing().x, 'X'); - gen_number(left_sidebearing().y, 'Y'); - gen_number(_width.x); - gen_number(_width.y); - gen_command(Cs::cSbw); - } - _state = S_CLOSED; -} - -void -Type1CharstringGenInterp::act_width(int, const Point &p) -{ - _width = p; -} - -void -Type1CharstringGenInterp::act_seac(int, double asb, double adx, double ady, int bchar, int achar) -{ - if (_state == S_INITIAL) - gen_sbw(false); - gen_number(asb); - gen_number(adx); - gen_number(ady); - gen_number(bchar); - gen_number(achar); - gen_command(Cs::cSeac); - _state = S_SEAC; -} - -void -Type1CharstringGenInterp::swap_stem_hints() -{ - _stem_pos.clear(); - _stem_width.clear(); - _stem_hstem.clear(); - _in_hr = true; -} - -void -Type1CharstringGenInterp::act_hstem(int, double pos, double width) -{ - if (_state != S_INITIAL && !_in_hr) - swap_stem_hints(); - _stem_pos.push_back(pos); - _stem_width.push_back(width); - _stem_hstem.push_back(1); -} - -void -Type1CharstringGenInterp::act_vstem(int, double pos, double width) -{ - if (_state != S_INITIAL && !_in_hr) - swap_stem_hints(); - _stem_pos.push_back(pos); - _stem_width.push_back(width); - _stem_hstem.push_back(0); -} - -String -Type1CharstringGenInterp::gen_hints(const unsigned char *data, int nhints) const -{ - _hint_csgen.clear(); - unsigned char mask = 0x80; - for (int i = 0; i < nhints; i++) { - if (*data & mask) { - double offset = (_stem_hstem[i] ? left_sidebearing().y : left_sidebearing().x); - _hint_csgen.gen_number(_stem_pos[i] - offset); - _hint_csgen.gen_number(_stem_width[i]); - _hint_csgen.gen_command(_stem_hstem[i] ? Cs::cHstem : Cs::cVstem); - } - if ((mask >>= 1) == 0) - data++, mask = 0x80; - } - return _hint_csgen.take_string(); -} - -void -Type1CharstringGenInterp::act_hintmask(int cmd, const unsigned char *data, int nhints) -{ - if (cmd == Cs::cCntrmask || nhints > Type1CharstringGenInterp::nhints()) - return; - - String data_holder; - if (!data) { - data_holder = String::make_fill('\377', ((nhints - 1) >> 3) + 1); - data = data_holder.udata(); - } - - String hints = gen_hints(data, nhints); - _in_hr = false; - - if (_state == S_INITIAL || _direct_hr) { - _last_hints = hints; - if (_state == S_INITIAL) - gen_sbw(true); - _csgen.append_charstring(hints); - } else if (_hr_storage && hints != _last_hints) { - _last_hints = hints; - hints += (char)(Cs::cReturn); - - int subrno = -1, nsubrs = _hr_storage->nsubrs(); - for (int i = _hr_firstsubr; i < nsubrs; i++) - if (Type1Subr *s = _hr_storage->subr_x(i)) - if (s->t1cs() == hints) { - subrno = i; - break; - } - - if (subrno < 0 && _hr_storage->set_subr(nsubrs, Type1Charstring(hints))) - subrno = nsubrs; - - if (subrno >= 0) { - _had_hr = true; - _csgen.gen_number(subrno); - _csgen.gen_number(4); - _csgen.gen_command(Cs::cCallsubr); - } - } -} - -void -Type1CharstringGenInterp::act_line(int cmd, const Point &a, const Point &b) -{ - if (_state == S_INITIAL) - gen_sbw(false); - else if (_in_hr) - act_hintmask(cmd, 0, nhints()); - _csgen.gen_moveto(a, _state == S_OPEN, false); - _state = S_OPEN; - if (a.x == b.x) { - gen_number(b.y - a.y, 'y'); - gen_command(Cs::cVlineto); - } else if (a.y == b.y) { - gen_number(b.x - a.x, 'x'); - gen_command(Cs::cHlineto); - } else { - gen_number(b.x - a.x, 'x'); - gen_number(b.y - a.y, 'y'); - gen_command(Cs::cRlineto); - } -} - -void -Type1CharstringGenInterp::act_curve(int cmd, const Point &a, const Point &b, const Point &c, const Point &d) -{ - if (_state == S_INITIAL) - gen_sbw(false); - else if (_in_hr) - act_hintmask(cmd, 0, nhints()); - _csgen.gen_moveto(a, _state == S_OPEN, false); - _state = S_OPEN; - if (b.y == a.y && d.x == c.x) { - gen_number(b.x - a.x, 'x'); - gen_number(c.x - b.x, 'x'); - gen_number(c.y - b.y, 'y'); - gen_number(d.y - c.y, 'y'); - gen_command(Cs::cHvcurveto); - } else if (b.x == a.x && d.y == c.y) { - gen_number(b.y - a.y, 'y'); - gen_number(c.x - a.x, 'x'); - gen_number(c.y - b.y, 'y'); - gen_number(d.x - c.x, 'x'); - gen_command(Cs::cVhcurveto); - } else { - gen_number(b.x - a.x, 'x'); - gen_number(b.y - a.y, 'y'); - gen_number(c.x - b.x, 'x'); - gen_number(c.y - b.y, 'y'); - gen_number(d.x - c.x, 'x'); - gen_number(d.y - c.y, 'y'); - gen_command(Cs::cRrcurveto); - } -} - -void -Type1CharstringGenInterp::act_flex(int cmd, const Point &p0, const Point &p1, const Point &p2, const Point &p3_4, const Point &p5, const Point &p6, const Point &p7, double flex_depth) -{ - if (_state == S_INITIAL) - gen_sbw(false); - else if (_in_hr) - act_hintmask(cmd, 0, nhints()); - _csgen.gen_moveto(p0, _state == S_OPEN, false); - _state = S_OPEN; - - // 1. Outer endpoints must have same x (or y) coordinate - bool v_ok = (p0.x == p7.x); - bool h_ok = (p0.y == p7.y); - - // 2. Join point and its neighboring controls must be at an extreme - if (v_ok && p2.x == p3_4.x && p3_4.x == p5.x) { - double distance = fabs(p3_4.x - p0.x); - int sign = (p3_4.x < p0.x ? -1 : 1); - if (sign * (p1.x - p0.x) < 0 || sign * (p1.x - p0.x) > distance - || sign * (p6.x - p0.x) < 0 || sign * (p6.x - p0.x) > distance) - v_ok = false; - } else - v_ok = false; - - if (h_ok && p2.y == p3_4.y && p3_4.y == p5.y) { - double distance = fabs(p3_4.y - p0.y); - int sign = (p3_4.y < p0.y ? -1 : 1); - if (sign * (p1.y - p0.y) < 0 || sign * (p1.y - p0.y) > distance - || sign * (p6.y - p0.y) < 0 || sign * (p6.y - p0.y) > distance) - h_ok = false; - } else - h_ok = false; - - // 3. Flex height <= 20 - if (v_ok && fabs(p3_4.x - p0.x) > 20) - v_ok = false; - if (h_ok && fabs(p3_4.y - p0.y) > 20) - h_ok = false; - - // generate flex commands - if (v_ok || h_ok) { - _had_flex = true; - Point p_reference = (h_ok ? Point(p3_4.x, p0.y) : Point(p0.x, p3_4.y)); - - _csgen.gen_number(1); - _csgen.gen_command(Cs::cCallsubr); - - _csgen.gen_moveto(p_reference, false, true); - _csgen.gen_number(2); - _csgen.gen_command(Cs::cCallsubr); - - _csgen.gen_moveto(p1, false, true); - _csgen.gen_number(2); - _csgen.gen_command(Cs::cCallsubr); - - _csgen.gen_moveto(p2, false, true); - _csgen.gen_number(2); - _csgen.gen_command(Cs::cCallsubr); - - _csgen.gen_moveto(p3_4, false, true); - _csgen.gen_number(2); - _csgen.gen_command(Cs::cCallsubr); - - _csgen.gen_moveto(p5, false, true); - _csgen.gen_number(2); - _csgen.gen_command(Cs::cCallsubr); - - _csgen.gen_moveto(p6, false, true); - _csgen.gen_number(2); - _csgen.gen_command(Cs::cCallsubr); - - _csgen.gen_moveto(p7, false, true); - _csgen.gen_number(2); - _csgen.gen_command(Cs::cCallsubr); - - _csgen.gen_number(flex_depth); - _csgen.gen_number(p7.x, 'X'); - _csgen.gen_number(p7.y, 'Y'); - _csgen.gen_number(0); - _csgen.gen_command(Cs::cCallsubr); - - double flex_height = fabs(h_ok ? p3_4.y - p0.y : p3_4.x - p0.x); - if (flex_height > _max_flex_height) - _max_flex_height = flex_height; - } else { - _had_bad_flex = true; - act_curve(cmd, p0, p1, p2, p3_4); - act_curve(cmd, p3_4, p5, p6, p7); - } -} - -void -Type1CharstringGenInterp::act_closepath(int cmd) -{ - if (_in_hr) - act_hintmask(cmd, 0, nhints()); - gen_command(Cs::cClosepath); - _state = S_CLOSED; -} - -void -Type1CharstringGenInterp::intermediate_output(Type1Charstring &out) -{ - _csgen.output(out); - _state = S_INITIAL; - act_hintmask(Cs::cEndchar, 0, nhints()); -} - -void -Type1CharstringGenInterp::run(const CharstringContext &g, Type1Charstring &out) -{ - _width = Point(0, 0); - _csgen.clear(); - swap_stem_hints(); - _state = S_INITIAL; - _in_hr = false; - - CharstringInterp::interpret(g); - - if (_state == S_INITIAL) - gen_sbw(false); - else if (_in_hr) - act_hintmask(Cs::cEndchar, 0, nhints()); - if (_state != S_SEAC) - _csgen.gen_command(Cs::cEndchar); - - _csgen.output(out); -} - -} |