diff options
author | Peter Breitenlohner <peb@mppmu.mpg.de> | 2015-09-27 12:22:13 +0000 |
---|---|---|
committer | Peter Breitenlohner <peb@mppmu.mpg.de> | 2015-09-27 12:22:13 +0000 |
commit | 19153a1e0e99364de1173ae9144a45e2518d88bb (patch) | |
tree | 1ade05d0a31ac88f7bea0d99598e3292c7e88ce7 /Build/source/texk/lcdf-typetools/lcdf-typetools-2.105/libefont/t1mm.cc | |
parent | adfd582cb6fc0c9b6ebf5055bd48af124dd4ee9e (diff) |
lcdf-typetools 2.105
git-svn-id: svn://tug.org/texlive/trunk@38471 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/lcdf-typetools/lcdf-typetools-2.105/libefont/t1mm.cc')
-rw-r--r-- | Build/source/texk/lcdf-typetools/lcdf-typetools-2.105/libefont/t1mm.cc | 393 |
1 files changed, 393 insertions, 0 deletions
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.105/libefont/t1mm.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.105/libefont/t1mm.cc new file mode 100644 index 00000000000..c15d103d94c --- /dev/null +++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.105/libefont/t1mm.cc @@ -0,0 +1,393 @@ +// -*- related-file-name: "../include/efont/t1mm.hh" -*- + +/* t1mm.{cc,hh} -- Type 1 multiple master font information + * + * Copyright (c) 1998-2014 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/t1mm.hh> +#include <efont/t1interp.hh> +#include <lcdf/error.hh> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +namespace Efont { + +MultipleMasterSpace::MultipleMasterSpace(PermString fn, int na, int nm) + : CharstringProgram(1000), + _ok(false), _font_name(fn), _naxes(na), _nmasters(nm), + _axis_types(na, PermString()), _axis_labels(na, PermString()), + _design_vector(0), _norm_design_vector(0), _weight_vector(0) +{ +} + + +void +MultipleMasterSpace::set_master_positions(const Vector<NumVector> &mp) +{ + _master_positions = mp; +} + +void +MultipleMasterSpace::set_normalize(const Vector<NumVector> &nin, + const Vector<NumVector> &nout) +{ + _normalize_in = nin; + _normalize_out = nout; +} + +void +MultipleMasterSpace::set_axis_type(int ax, PermString t) +{ + _axis_types[ax] = t; +} + +void +MultipleMasterSpace::set_axis_label(int ax, PermString t) +{ + _axis_labels[ax] = t; +} + +void +MultipleMasterSpace::set_design_vector(const NumVector &v) +{ + _default_design_vector = v; +} + +void +MultipleMasterSpace::set_weight_vector(const NumVector &v) +{ + _default_weight_vector = v; +} + + +PermString +MultipleMasterSpace::axis_abbreviation(PermString atype) +{ + if (atype == "Weight") + return "wt"; + else if (atype == "Width") + return "wd"; + else if (atype == "OpticalSize") + return "op"; + else if (atype == "Style") + return "st"; + else + return atype; +} + + +bool +MultipleMasterSpace::error(ErrorHandler *errh, const char *s, ...) const +{ + if (errh) { + char buf[1024]; + va_list val; + va_start(val, s); + assert(strlen(s) < 800); + sprintf(buf, (s[0] == ' ' ? "%.200s%s" : "%.200s: %s"), + _font_name.c_str(), s); + errh->vxmessage(ErrorHandler::e_error, buf, val); + va_end(val); + } + return false; +} + + +bool +MultipleMasterSpace::check(ErrorHandler *errh) +{ + if (_ok) + return true; + + if (_nmasters <= 0 || _nmasters > 16) + return error(errh, "number of masters must be between 1 and 16"); + if (_naxes <= 0 || _naxes > 4) + return error(errh, "number of axes must be between 1 and 4"); + + if (_master_positions.size() != _nmasters) + return error(errh, "bad BlendDesignPositions"); + for (int i = 0; i < _nmasters; i++) + if (_master_positions[i].size() != _naxes) + return error(errh, "inconsistent BlendDesignPositions"); + + if (_normalize_in.size() != _naxes || _normalize_out.size() != _naxes) + return error(errh, "bad BlendDesignMap"); + for (int i = 0; i < _naxes; i++) + if (_normalize_in[i].size() != _normalize_out[i].size()) + return error(errh, "bad BlendDesignMap"); + + if (!_axis_types.size()) + _axis_types.assign(_naxes, PermString()); + if (_axis_types.size() != _naxes) + return error(errh, "bad BlendAxisTypes"); + + if (!_axis_labels.size()) + _axis_labels.assign(_naxes, PermString()); + if (_axis_labels.size() != _naxes) + return error(errh, "bad axis labels"); + + if (!_default_design_vector.size()) + _default_design_vector.assign(_naxes, UNKDOUBLE); + if (_default_design_vector.size() != _naxes) + return error(errh, "inconsistent design vector"); + + if (!_default_weight_vector.size()) + _default_weight_vector.assign(_nmasters, UNKDOUBLE); + if (_default_weight_vector.size() != _nmasters) + return error(errh, "inconsistent weight vector"); + + _ok = true; + return true; +} + +bool +MultipleMasterSpace::check_intermediate(ErrorHandler *errh) +{ + if (!_ok || _cdv) + return true; + + for (int a = 0; a < _naxes; a++) + for (int m = 0; m < _nmasters; m++) + if (_master_positions[m][a] != 0 && _master_positions[m][a] != 1) { + if (errh) + errh->warning("%s requires intermediate master conversion programs", + _font_name.c_str()); + return false; + } + + return true; +} + + +int +MultipleMasterSpace::axis(PermString ax) const +{ + for (int a = 0; a < _naxes; a++) + if (_axis_types[a] == ax || _axis_labels[a] == ax) + return a; + return -1; +} + +double +MultipleMasterSpace::axis_low(int ax) const +{ + return _normalize_in[ax][0]; +} + +double +MultipleMasterSpace::axis_high(int ax) const +{ + return _normalize_in[ax].back(); +} + + +Vector<double> +MultipleMasterSpace::empty_design_vector() const +{ + return Vector<double>(_naxes, UNKDOUBLE); +} + +bool +MultipleMasterSpace::set_design(NumVector &design_vector, int ax, double value, + ErrorHandler *errh) const +{ + if (ax < 0 || ax >= _naxes) + return error(errh, " has only %d axes", _naxes); + + if (value < axis_low(ax)) { + value = axis_low(ax); + if (errh) + errh->warning("raising %s's %s to %g", _font_name.c_str(), + _axis_types[ax].c_str(), value); + } + if (value > axis_high(ax)) { + value = axis_high(ax); + if (errh) + errh->warning("lowering %s's %s to %g", _font_name.c_str(), + _axis_types[ax].c_str(), value); + } + + design_vector[ax] = value; + return true; +} + +bool +MultipleMasterSpace::set_design(NumVector &design_vector, PermString ax_name, + double val, ErrorHandler *errh) const +{ + int ax = axis(ax_name); + if (ax < 0) + return error(errh, " has no `%s' axis", ax_name.c_str()); + else + return set_design(design_vector, ax, val, errh); +} + + +bool +MultipleMasterSpace::normalize_vector(ErrorHandler *errh) const +{ + NumVector &design = *_design_vector; + NumVector &norm_design = *_norm_design_vector; + + for (int a = 0; a < _naxes; a++) + if (!KNOWN(design[a])) { + if (errh) + errh->error("must specify %s's %s coordinate", _font_name.c_str(), _axis_types[a].c_str()); + return false; + } + + // Move to normalized design coordinates. + norm_design.assign(_naxes, UNKDOUBLE); + + if (_ndv) { + CharstringInterp ai; + if (!ai.interpret(this, &_ndv)) + return error(errh, "%s in NDV program", ai.error_string().c_str()); + + } else + for (int a = 0; a < _naxes; a++) { + double d = design[a]; + double nd = UNKDOUBLE; + const Vector<double> &norm_in = _normalize_in[a]; + const Vector<double> &norm_out = _normalize_out[a]; + + if (d < norm_in[0]) + nd = norm_out[0]; + for (int i = 1; i < norm_in.size(); i++) + if (d >= norm_in[i-1] && d < norm_in[i]) { + nd = norm_out[i-1] + + ((d - norm_in[i-1]) + * (norm_out[i] - norm_out[i-1]) + / (norm_in[i] - norm_in[i-1])); + goto done; + } + if (d >= norm_in.back()) + nd = norm_out.back(); + + done: + norm_design[a] = nd; + } + + for (int a = 0; a < _naxes; a++) + if (!KNOWN(norm_design[a])) + return error(errh, "bad normalization"); + + return true; +} + + +bool +MultipleMasterSpace::convert_vector(ErrorHandler *errh) const +{ + NumVector &norm_design = *_norm_design_vector; + NumVector &weight = *_weight_vector; + + weight.assign(_nmasters, 1); + + if (_cdv) { + CharstringInterp ai; + if (!ai.interpret(this, &_cdv)) + return error(errh, "%s in CDV program", ai.error_string().c_str()); + + } else + for (int a = 0; a < _naxes; a++) + for (int m = 0; m < _nmasters; m++) { + if (_master_positions[m][a] == 0) + weight[m] *= 1 - norm_design[a]; + else if (_master_positions[m][a] == 1) + weight[m] *= norm_design[a]; + else + return error(errh, " requires intermediate master conversion programs"); + } + + return true; +} + + +bool +MultipleMasterSpace::design_to_norm_design(const NumVector &design_in, + NumVector &norm_design, + ErrorHandler *errh) const +{ + NumVector design(design_in); + NumVector weight; + + _design_vector = &design; + _norm_design_vector = &norm_design; + _weight_vector = &weight; + if (!normalize_vector(errh)) + return false; + _design_vector = _norm_design_vector = _weight_vector = 0; + + return true; +} + + +bool +MultipleMasterSpace::design_to_weight(const NumVector &design_in, NumVector &weight, ErrorHandler *errh) const +{ + NumVector design(design_in); + NumVector norm_design; + + bool dirty = false; + for (int i = 0; i < _naxes; i++) + if (design[i] != _default_design_vector[i]) + dirty = true; + + if (dirty) { + _design_vector = &design; + _norm_design_vector = &norm_design; + _weight_vector = &weight; + if (!normalize_vector(errh)) + return false; + if (!convert_vector(errh)) + return false; + _design_vector = _norm_design_vector = _weight_vector = 0; + } else + weight = _default_weight_vector; + + double sum = 0; + for (int m = 0; m < _nmasters; m++) + sum += weight[m]; + if (sum < 0.9999 || sum > 1.0001) + return error(errh, "bad conversion: weight vector doesn't sum to 1"); + + // adjust weight vector to max 4 decimal digits of precision, and make it + // sum to exactly 1 + sum = 0; + for (int m = 0; m < _nmasters - 1; m++) { + weight[m] = floor(weight[m] * 10000. + 0.5) / 10000.; + sum += weight[m]; + } + weight[_nmasters - 1] = 1 - sum; + + return true; +} + + +Vector<double> * +MultipleMasterSpace::mm_vector(VectorType t, bool writable) const +{ + if (t == VEC_WEIGHT) + return _weight_vector; + else if (t == VEC_NORM_DESIGN) + return _norm_design_vector; + else if (t == VEC_DESIGN && !writable) + return _design_vector; + else + return 0; +} + +} |