w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

metrics.cc
Go to the documentation of this file.
1 /* metrics.{cc,hh} -- an encoding during and after OpenType features
2  *
3  * Copyright (c) 2003-2019 Eddie Kohler
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the Free
7  * Software Foundation; either version 2 of the License, or (at your option)
8  * any later version. This program is distributed in the hope that it will be
9  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11  * Public License for more details.
12  */
13 
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
17 #include "metrics.hh"
18 #include "dvipsencoding.hh"
19 #include "util.hh"
20 #include "glyphfilter.hh"
21 #include <string.h>
22 #include <stdio.h>
23 #include <algorithm>
24 #include <lcdf/straccum.hh>
25 
27  : _boundary_glyph(nglyphs), _emptyslot_glyph(nglyphs + 1),
28  _design_units(1000), _units_per_em(font->units_per_em()),
29  _liveness_marked(false)
30 {
31  _encoding.assign(256, Char());
33 }
34 
36 {
37  for (Char *c = _encoding.begin(); c != _encoding.end(); c++)
38  delete c->virtual_char;
39 }
40 
41 int
43 {
44  _mapped_fonts.push_back(font);
45  _mapped_font_names.push_back(name);
46  return _mapped_fonts.size() - 1;
47 }
48 
49 void
51 {
52  // check invariants
53  // 1. all 'ligatures' entries refer to valid characters
54  // 2. all 'ligatures' entries with 'in1 == c' are in '_encoding[c].ligs'
55  // 3. 'virtual_char' SHOW operations point to valid non-virtual chars
56  for (int code = 0; code < _encoding.size(); code++) {
57  const Char *ch = &_encoding[code];
58  assert((ch->virtual_char != 0) == (ch->glyph == VIRTUAL_GLYPH));
59  for (const Ligature *l = ch->ligatures.begin(); l != ch->ligatures.end(); l++)
60  assert(valid_code(l->in2) && valid_code(l->out));
61  for (const Kern *k = ch->kerns.begin(); k != ch->kerns.end(); k++)
62  assert(valid_code(k->in2));
63  if (const VirtualChar *vc = ch->virtual_char) {
64  assert(vc->name);
65  int font_number = 0;
66  for (const Setting *s = vc->setting.begin(); s != vc->setting.end(); s++) {
67  assert(s->valid_op());
68  if (s->op == Setting::SHOW && font_number == 0)
70  else if (s->op == Setting::FONT)
71  font_number = s->x;
72  }
73  }
74  assert(ch->built_in1 < 0 || valid_code(ch->built_in1));
75  assert(ch->built_in2 < 0 || valid_code(ch->built_in2));
76  assert((ch->built_in1 >= 0) == (ch->built_in2 >= 0));
77  assert(ch->base_code < 0 || valid_code(ch->base_code));
78  if (valid_code(ch->base_code)) {
79  const Char *ch2 = &_encoding[ch->base_code];
80  assert((!ch->virtual_char && ch->glyph)
81  || (!ch2->virtual_char && ch2->glyph));
82  }
83  if (ch->flag(Char::CONTEXT_ONLY))
84  assert(ch->virtual_char && ch->built_in1 >= 0 && ch->built_in2 >= 0);
85  if (ch->flag(Char::CONTEXT_ONLY))
86  assert(ch->flag(Char::LIVE));
87  }
88 }
89 
92 {
93  if (code < 0 || code >= _encoding.size())
94  return permprintf("<badcode%d>", code);
95  else {
96  const Char &ch = _encoding[code];
97  if (ch.virtual_char)
98  return ch.virtual_char->name;
99  else if (ch.glyph == _boundary_glyph)
100  return "<boundary>";
101  else if (ch.glyph == _emptyslot_glyph)
102  return "<emptyslot>";
103  else if (ch.glyph >= 0 && ch.glyph < _mapped_fonts[0]->nglyphs())
104  return _mapped_fonts[0]->glyph_name(ch.glyph);
105  else
106  return permprintf("<glyph%d>", ch.glyph);
107  }
108 }
109 
110 
111 /*****************************************************************************/
112 /* encoding */
113 
116 {
117  for (const Char *ch = _encoding.begin(); ch < _encoding.end(); ch++)
118  if (ch->unicode == uni)
119  return ch - _encoding.begin();
120  return -1;
121 }
122 
125 {
126  if (g < 0)
127  return -1;
128  int answer = -1, n = 0;
129  for (int i = _encoding.size() - 1; i >= after; i--)
130  if (_encoding[i].glyph == g)
131  answer = i, n++;
132  if (n < 2 && after == 0) {
133  if (g >= _emap.size())
134  _emap.resize(g + 1, -2);
135  _emap[g] = answer;
136  }
137  return answer;
138 }
139 
141 Metrics::force_encoding(Glyph g, int lookup_source)
142 {
143  assert(g >= 0);
144  int e = encoding(g, 0);
145  if (e >= 0)
146  return e;
147  else {
148  Char ch;
149  ch.glyph = g;
150  ch.base_code = _encoding.size();
151  ch.lookup_source = lookup_source;
152  _encoding.push_back(ch);
153  assign_emap(g, ch.base_code);
154  return ch.base_code;
155  }
156 }
157 
158 void
160 {
161  assert(code >= 0 && g >= 0 && g != VIRTUAL_GLYPH);
162  if (code >= _encoding.size())
163  _encoding.resize(code + 1, Char());
164  _encoding[code].unicode = uni;
165  _encoding[code].glyph = g;
166  if (g > 0)
167  _encoding[code].base_code = code;
168  assert(!_encoding[code].virtual_char);
169  assign_emap(g, code);
170 }
171 
172 void
174 {
175  assert(code >= 0 && v.size() > 0);
176  if (code >= _encoding.size())
177  _encoding.resize(code + 1, Char());
178  _encoding[code].unicode = uni;
179  _encoding[code].glyph = VIRTUAL_GLYPH;
180  if (base_char)
181  _encoding[code].flags |= Char::BASE_REP;
182  assert(!_encoding[code].virtual_char);
183  VirtualChar *vc = _encoding[code].virtual_char = new VirtualChar;
184  vc->name = name;
185  vc->setting = v;
186  int font_number = 0;
187  for (Setting *s = vc->setting.begin(); s != vc->setting.end(); s++) {
188  assert(s->valid_op() && (s->op != Setting::SHOW || font_number != 0 || nonvirtual_code(s->x)));
189  if (s->op == Setting::FONT)
190  font_number = s->x;
191  }
192 }
193 
194 void
196 {
197  int font_number = -1;
198  for (Char *c = _encoding.begin(); c != _encoding.end(); c++)
199  if (c->glyph > 0 && !c->virtual_char && c->glyph < mapping.size()
200  && mapping[c->glyph] >= 0) {
201  if (font_number < 0)
202  font_number = add_mapped_font(mapped_font(0), font_name);
203  VirtualChar *vc = c->virtual_char = new VirtualChar;
204  vc->name = dvipsenc.encoding(mapping[c->glyph]);
205  vc->setting.push_back(Setting(Setting::FONT, font_number));
206  vc->setting.push_back(Setting(Setting::SHOW, mapping[c->glyph], c->glyph));
207  c->glyph = VIRTUAL_GLYPH;
208  c->base_code = -1;
209  c->flags = (c->flags & ~~Char::BASE_LIVE) | Char::BASE_REP;
210  }
211 }
212 
213 void
215 {
216  for (Kern *k = _altselectors.begin(); k != _altselectors.end(); k++)
217  if (k->in2 == code) {
218  k->kern = altselector_type;
219  return;
220  }
221  _altselectors.push_back(Kern(code, altselector_type));
222 }
223 
224 bool
226 {
227  bool any = false;
228  v.assign(_encoding.size(), 0);
229  for (const Char *ch = _encoding.begin(); ch != _encoding.end(); ch++)
230  if (ch->base_code >= 0 && ch->base_code < size) {
231  v[ch->base_code] = ch->glyph;
232  any = true;
233  }
234  return any;
235 }
236 
237 
238 /*****************************************************************************/
239 /* Char methods */
240 
241 void
243 {
244  glyph = 0;
245  base_code = -1;
246  unicode = 0;
247  ligatures.clear();
248  kerns.clear();
249  delete virtual_char;
250  virtual_char = 0;
251  pdx = pdy = adx = 0;
252  built_in1 = built_in2 = -1;
253  lookup_source = -1;
254  flags = 0;
255 }
256 
257 void
259 {
260  std::swap(glyph, c.glyph);
261  // NB: only a partial switch of base_code!!
262  if (base_code < 0)
263  base_code = c.base_code;
264  c.base_code = -1;
265  std::swap(unicode, c.unicode);
266  ligatures.swap(c.ligatures);
267  kerns.swap(c.kerns);
268  std::swap(virtual_char, c.virtual_char);
269  std::swap(pdx, c.pdx);
270  std::swap(pdy, c.pdy);
271  std::swap(adx, c.adx);
272  std::swap(built_in1, c.built_in1);
273  std::swap(built_in2, c.built_in2);
274  std::swap(lookup_source, c.lookup_source);
275  std::swap(flags, c.flags);
276 }
277 
278 
279 /*****************************************************************************/
280 /* manipulating ligature lists */
281 
284 {
285  assert(valid_code(code1) && valid_code(code2));
286  Char &ch = _encoding[code1];
287  for (Ligature *l = ch.ligatures.begin(); l != ch.ligatures.end(); l++)
288  if (l->in2 == code2)
289  return l;
290  return 0;
291 }
292 
293 inline void
295 {
296  assert(valid_code(in1) && valid_code(in2) && valid_code(out));
297  _encoding[in1].ligatures.push_back(Ligature(in2, out));
298 }
299 
300 inline void
302 {
303  l->out = out;
304 }
305 
306 void
308 {
309  if (Ligature *l = ligature_obj(in1, in2)) {
310  Char &ch = _encoding[l->out];
311  if (ch.flags & Char::BUILT) {
312  // move old ligatures to point to the true ligature
313  for (Ligature *ll = ch.ligatures.begin(); ll != ch.ligatures.end(); ll++)
314  add_ligature(out, ll->in2, ll->out);
315  repoint_ligature(in1, l, out);
316  }
317  } else
318  new_ligature(in1, in2, out);
319 }
320 
322 Metrics::pair_code(Code in1, Code in2, int lookup_source)
323 {
324  if (const Ligature *l = ligature_obj(in1, in2)) {
325  if (lookup_source < 0)
326  _encoding[l->out].flags &= ~~Char::INTERMEDIATE;
327  return l->out;
328  } else {
329  Char ch;
330  ch.glyph = VIRTUAL_GLYPH;
331  ch.flags = Char::BUILT | (lookup_source >= 0 ? Char::INTERMEDIATE : 0);
332  VirtualChar *vc = ch.virtual_char = new VirtualChar;
333  vc->name = permprintf("%s__%s", code_str(in1), code_str(in2));
334  setting(in1, vc->setting, SET_INTERMEDIATE);
335  vc->setting.push_back(Setting(Setting::KERN));
336  setting(in2, vc->setting, SET_INTERMEDIATE);
337  ch.built_in1 = in1;
338  ch.built_in2 = in2;
339  ch.lookup_source = lookup_source;
340  _encoding.push_back(ch);
341  new_ligature(in1, in2, _encoding.size() - 1);
342  return _encoding.size() - 1;
343  }
344 }
345 
346 void
348 {
349  if (in1 == CODE_ALL) {
350  for (in1 = 0; in1 < _encoding.size(); in1++)
351  remove_ligatures(in1, in2);
352  } else {
353  Char &ch = _encoding[in1];
354  if (in2 == CODE_ALL)
355  ch.ligatures.clear();
356  else if (Ligature *l = ligature_obj(in1, in2)) {
357  *l = ch.ligatures.back();
358  ch.ligatures.pop_back();
359  }
360  }
361 }
362 
363 
364 /*****************************************************************************/
365 /* manipulating kern lists */
366 
369 {
370  assert(valid_code(in1) && valid_code(in2));
371  Char &ch = _encoding[in1];
372  for (Kern *k = ch.kerns.begin(); k != ch.kerns.end(); k++)
373  if (k->in2 == in2)
374  return k;
375  return 0;
376 }
377 
378 int
379 Metrics::kern(Code in1, Code in2) const
380 {
381  assert(valid_code(in1) && valid_code(in2));
382  const Char &ch = _encoding[in1];
383  for (const Kern *k = ch.kerns.begin(); k != ch.kerns.end(); k++)
384  if (k->in2 == in2)
385  return k->kern;
386  return 0;
387 }
388 
389 void
391 {
392  if (Kern *k = kern_obj(in1, in2))
393  k->kern += kern;
394  else
395  _encoding[in1].kerns.push_back(Kern(in2, kern));
396 }
397 
398 void
400 {
401  if (in1 == CODE_ALL) {
402  for (in1 = 0; in1 < _encoding.size(); in1++)
403  set_kern(in1, in2, kern);
404  } else {
405  Char &ch = _encoding[in1];
406  if (in2 == CODE_ALL) {
407  assert(kern == 0);
408  ch.kerns.clear();
409  } else if (Kern *k = kern_obj(in1, in2)) {
410  if (kern == 0) {
411  *k = ch.kerns.back();
412  ch.kerns.pop_back();
413  } else
414  k->kern = kern;
415  } else if (kern != 0)
416  ch.kerns.push_back(Kern(in2, kern));
417  }
418 }
419 
420 int
422 {
423  int nchanges = 0;
424  for (Char *ch = _encoding.begin(); ch != _encoding.end(); ch++) {
425  for (Ligature *l = ch->ligatures.begin(); l != ch->ligatures.end(); l++)
426  if (l->in2 == old_in2) {
427  if (new_in2 >= 0)
428  l->in2 = new_in2;
429  else {
430  *l = ch->ligatures.back();
431  ch->ligatures.pop_back();
432  l--;
433  }
434  nchanges++;
435  }
436  for (Kern *k = ch->kerns.begin(); k != ch->kerns.end(); k++)
437  if (k->in2 == old_in2) {
438  if (new_in2 >= 0)
439  k->in2 = new_in2;
440  else {
441  *k = ch->kerns.back();
442  ch->kerns.pop_back();
443  k--;
444  }
445  nchanges++;
446  }
447  // XXX?
448  if (ch->context_setting(-1, old_in2) && new_in2 >= 0 && ch->built_in1 >= 0)
449  ch->built_in2 = new_in2;
450  }
451  return nchanges;
452 }
453 
454 
455 /*****************************************************************************/
456 /* positioning */
457 
458 void
459 Metrics::add_single_positioning(Code c, int pdx, int pdy, int adx)
460 {
461  assert(valid_code(c));
462  Char &ch = _encoding[c];
463  ch.pdx += pdx;
464  ch.pdy += pdy;
465  ch.adx += adx;
466 }
467 
468 
469 /*****************************************************************************/
470 /* changed_context structure */
471 
472 class Metrics::ChangedContext { public:
473  ChangedContext(int ncodes);
474  ~ChangedContext();
476 
477  enum Context { CH_NONE = 0, CH_SOME = 1, CH_ALL = 2 };
478  bool allowed(Code, bool left_context) const;
479  bool pair_allowed(Code, Code) const;
480  bool virgin(Code) const;
481  void disallow(Code);
482  void disallow_pair(Code, Code);
483  private:
489  static inline bool bit(const Vector<uint32_t> &, Code);
490  inline void ensure_all(Code) const;
491 };
492 
494  : _v(ncodes, 0), _initial_ncodes(ncodes), _all_sentinel(((ncodes - 1) >> 5) + 1, 0xFFFFFFFFU)
495 {
496 }
497 
499 {
500  for (Vector<uint32_t> **v = _v.begin(); v != _v.end(); v++)
501  if (*v != &_all_sentinel)
502  delete *v;
503 }
504 
505 inline void
507 {
508  if (c >= 0 && (c >> 5) >= _all_sentinel.size())
509  _all_sentinel.resize((c >> 5) + 1, 0xFFFFFFFFU);
510 }
511 
512 inline bool
514 {
515  if (c < 0 || (c >> 5) >= v.size())
516  return false;
517  else
518  return (v[c >> 5] & (1 << (c & 0x1F))) != 0;
519 }
520 
521 bool
522 Metrics::ChangedContext::allowed(Code c, bool left_context) const
523 {
524  if (c < 0)
525  return false;
526  else if (c >= _v.size())
527  return left_context;
528  else
529  return (_v[c] != &_all_sentinel);
530 }
531 
532 bool
534 {
535  ensure_all(c2);
536  if (c1 < 0 || c2 < 0)
537  return false;
538  else if (c1 >= _v.size() || c2 >= _v.size() || !_v[c1])
539  return true;
540  else
541  return !bit(*_v[c1], c2);
542 }
543 
544 bool
546 {
547  return (c >= 0 && (c >= _v.size() || _v[c] == 0));
548 }
549 
550 void
552 {
553  assert(c >= 0);
554  if (c >= _v.size())
555  _v.resize(c + 1, 0);
556  if (_v[c] != &_all_sentinel) {
557  delete _v[c];
558  _v[c] = &_all_sentinel;
559  }
560 }
561 
562 void
564 {
565  assert(c1 >= 0 && c2 >= 0);
566  if (c1 >= _v.size())
567  _v.resize(c1 + 1, 0);
568  if (!_v[c1])
569  _v[c1] = new Vector<uint32_t>;
570  if (_v[c1] != &_all_sentinel) {
571  if ((c2 >> 5) >= _v[c1]->size())
572  _v[c1]->resize((c2 >> 5) + 1, 0);
573  (*_v[c1])[c2 >> 5] |= 1 << (c2 & 0x1F);
574  }
575 }
576 
577 
578 /*****************************************************************************/
579 /* applying GSUB substitutions */
580 
581 void
583  ChangedContext &ctx, const GlyphFilter &glyph_filter,
584  const Vector<PermString> &glyph_names)
585 {
586  // check if encoded
587  if (!ctx.allowed(cin, false))
588  /* not encoded before this substitution began, or completely changed;
589  ingore */
590  return;
591 
592  // check if substitution of this code allowed
593  if (!glyph_filter.allow_substitution(s->in_glyph(), glyph_names, unicode(cin)))
594  return;
595 
596  // look for an allowed alternate
597  Glyph out = -1;
598  for (int i = 0; out < 0 && i < s->out_nglyphs(); i++)
599  if (glyph_filter.allow_alternate(s->out_glyph(i), glyph_names, unicode(cin)))
600  out = s->out_glyph(i);
601  if (out < 0) // no allowed alternate
602  return;
603 
604  // apply substitution
605  if (ctx.virgin(cin)) {
606  // no one has changed this glyph yet, change it unilaterally
607  assign_emap(s->in_glyph(), -2);
608  assign_emap(out, cin);
609  assert(!_encoding[cin].virtual_char);
610  _encoding[cin].glyph = out;
611  } else {
612  // some contextual substitutions have changed this glyph, add
613  // contextual substitutions for the remaining possibilities
614  Code cout = force_encoding(out, lookup);
615  for (Code right = 0; right < _encoding.size(); right++)
617  Code pair = pair_code(cout, right, lookup);
618  _encoding[cout].flags &= ~~Char::INTERMEDIATE;
619  add_ligature(cin, right, pair);
620  }
621  }
622 
623  // no more substitutions for cin
624  ctx.disallow(cin);
625 }
626 
627 void
629 {
630  // build up the character pair
631  int cin1 = in[0];
632  for (const Code *inp = in.begin() + 1; inp < in.end() - 1; inp++)
633  cin1 = pair_code(cin1, *inp, lookup);
634  int cin2 = in.back();
635 
636  // build up the output character
638  s->all_out_glyphs(out);
639  int cout = -1;
640  for (Glyph *outp = out.begin(); outp < out.end(); outp++) {
641  *outp = force_encoding(*outp, lookup);
642  cout = (cout < 0 ? *outp : pair_code(cout, *outp, lookup));
643  }
644  _encoding[cout].flags &= ~~Char::INTERMEDIATE;
645 
646  // check for replacing a fake ligature
647  int old_out = -1;
648  if (Ligature *l = ligature_obj(cin1, cin2)) {
649  if (l->out == cout) // already created this same ligature
650  return;
651  if (_encoding[l->out].flags & Char::BUILT)
652  old_out = l->out;
653  }
654 
655  // make the final ligature
656  add_ligature(cin1, cin2, cout);
657 
658  //fprintf(stderr, "%s : %d/%s %d/%s => %d/%s [was %d/%s]\n", s->unparse().c_str(), cin1, code_str(cin1), cin2, code_str(cin2), cout, code_str(cout), old_out, code_str(old_out));
659 
660  // if appropriate, swap old ligatures to point to the new result
661  if (old_out >= 0)
662  for (Char *ch = _encoding.begin(); ch != _encoding.end(); ch++)
663  for (Ligature *l = ch->ligatures.begin(); l != ch->ligatures.end(); l++)
664  if (l->out == old_out)
665  repoint_ligature(ch - _encoding.begin(), l, cout);
666 }
667 
668 void
670  const Substitution *s, int lookup, ChangedContext &ctx,
671  const GlyphFilter &glyph_filter,
672  const Vector<PermString>& glyph_names)
673 {
674  int nleft = s->left_nglyphs(), nin = s->in_nglyphs();
675  assert(codes.size() >= 2);
676 
677  // check if context allows substitutions
678  for (int i = 0; i < codes.size(); ++i) {
679  if (!ctx.allowed(codes[i], i < nleft)
680  || !glyph_filter.allow_substitution(s->in_glyph(i), glyph_names, unicode(codes[i])))
681  return;
682  }
683 
684  // check if any part of the combination has already changed
685  int ncheck = nleft + (nin > 2 ? 2 : nin);
686  if (ncheck == codes.size())
687  --ncheck;
688  for (const Code *inp = codes.begin(); inp < codes.begin() + ncheck; ++inp)
689  if (!ctx.pair_allowed(inp[0], inp[1]))
690  return;
691 
692  // mark this combination as changed if appropriate
693  if (codes.size() == 2 && nin == 1)
694  ctx.disallow_pair(codes[0], codes[1]);
695 
696  // actually apply ligature
697  apply_ligature(codes, s, lookup);
698 }
699 
700 bool
702 {
703  if (!codes.size()) {
704  codes.assign(glyphs.size(), 0);
705  for (int i = 0; i < glyphs.size(); ++i)
706  if ((codes[i] = encoding(glyphs[i], 0)) < 0)
707  return false;
708  return true;
709  } else {
710  for (int i = 0; i < glyphs.size(); ++i)
711  if ((codes[i] = encoding(glyphs[i], codes[i] + 1)) >= 0)
712  return true;
713  else
714  codes[i] = encoding(glyphs[i], 0);
715  return false;
716  }
717 }
718 
719 int
720 Metrics::apply(const Vector<Substitution>& sv, bool allow_single, int lookup, const GlyphFilter& glyph_filter, const Vector<PermString>& glyph_names)
721 {
723  Vector<Code> codes;
724 
725  // keep track of what substitutions we have performed
726  ChangedContext ctx(_encoding.size());
727 
728  // loop over substitutions
729  int failures = 0;
730  for (const Substitution *s = sv.begin(); s != sv.end(); s++) {
731  bool is_single = s->is_single() || s->is_alternate();
732  bool is_apply_single = is_single && allow_single;
733  bool is_apply_simple_context_ligature = !is_single && !s->is_multiple() && s->is_simple_context();
734 
735  if (is_apply_single || is_apply_simple_context_ligature) {
736  s->all_in_glyphs(glyphs);
737  for (codes.clear(); next_encoding(codes, glyphs); ) {
738  if (is_apply_single)
739  apply_single(codes[0], s, lookup, ctx, glyph_filter, glyph_names);
740  else
741  apply_simple_context_ligature(codes, s, lookup, ctx, glyph_filter, glyph_names);
742  }
743  } else
744  failures++;
745  }
746 
747  return sv.size() - failures;
748 }
749 
750 void
752  const GlyphFilter &glyph_filter,
753  const Vector<PermString> &glyph_names)
754 {
755  for (const Kern *as = _altselectors.begin(); as != _altselectors.end(); as++)
756  if (as->kern == 0) {
757  Code last = cin;
758  uint32_t u = unicode(cin);
759  for (int i = 0; i < s->out_nglyphs(); i++)
760  if (glyph_filter.allow_alternate(s->out_glyph(i), glyph_names, u)) {
761  Code out = force_encoding(s->out_glyph(i), lookup);
762  add_ligature(last, as->in2, out);
763  last = out;
764  }
765  } else if (as->kern <= s->out_nglyphs()) {
766  Code out = force_encoding(s->out_glyph(as->kern - 1), lookup);
767  add_ligature(cin, as->in2, out);
768  }
769 }
770 
771 void
773  const Substitution *s, int lookup,
774  const GlyphFilter &glyph_filter,
775  const Vector<PermString> &glyph_names)
776 {
777  // check whether the output character is allowed
778  if (!glyph_filter.allow_alternate(s->out_glyph(), glyph_names, 0))
779  return;
780 
781  // find alternate selector and apply ligature if appropriate
782  for (const Kern *as = _altselectors.begin(); as != _altselectors.end(); as++)
783  if (as->kern == 0) {
784  Vector<Code> lig(codes);
785  lig.insert(lig.begin() + 1, as->in2);
787  }
788 }
789 
790 void
791 Metrics::apply_alternates(const Vector<Substitution>& sv, int lookup, const GlyphFilter& glyph_filter, const Vector<PermString>& glyph_names)
792 {
794  Vector<Code> codes;
795 
796  for (const Substitution *s = sv.begin(); s != sv.end(); s++) {
797  bool is_single = s->is_single() || s->is_alternate();
798  if (is_single || s->is_ligature()) {
799  s->all_in_glyphs(glyphs);
800  for (codes.clear(); next_encoding(codes, glyphs); ) {
801  if (is_single)
802  apply_alternates_single(codes[0], s, lookup, glyph_filter, glyph_names);
803  else
804  apply_alternates_ligature(codes, s, lookup, glyph_filter, glyph_names);
805  }
806  }
807  }
808 }
809 
810 
811 /*****************************************************************************/
812 /* applying GPOS positionings */
813 
814 static bool // returns old value
815 assign_bitvec(int*& bitvec, int e, int n)
816 {
817  if (e >= 0 && e < n) {
818  if (!bitvec) {
819  bitvec = new int[((n - 1) >> 5) + 1];
820  memset(bitvec, 0, sizeof(int) * (((n - 1) >> 5) + 1));
821  }
822  bool result = (bitvec[e >> 5] & (1 << (e & 0x1F))) != 0;
823  bitvec[e >> 5] |= (1 << (e & 0x1F));
824  return result;
825  } else
826  return false;
827 }
828 
829 int
831 {
832  // keep track of what substitutions we have performed
833  int *single_changed = 0;
834  Vector<int *> pair_changed(_encoding.size(), 0);
836  Vector<Code> codes;
837 
838  // loop over substitutions
839  int success = 0;
840  for (const Positioning *p = pv.begin(); p != pv.end(); p++) {
841  bool is_single = p->is_single();
842  if (is_single || p->is_pairkern()) {
843  p->all_in_glyphs(glyphs);
844  for (codes.clear(); next_encoding(codes, glyphs); )
845  if (is_single) {
846  if (!assign_bitvec(single_changed, codes[0], _encoding.size())) {
847  _encoding[codes[0]].pdx += p->left().pdx;
848  _encoding[codes[0]].pdy += p->left().pdy;
849  _encoding[codes[0]].adx += p->left().adx;
850  }
851  } else {
852  if (!assign_bitvec(pair_changed[codes[0]], codes[1], _encoding.size()))
853  add_kern(codes[0], codes[1], p->left().adx);
854  }
855  success++;
856  }
857  }
858 
859  delete[] single_changed;
860  for (int i = 0; i < pair_changed.size(); i++)
861  delete[] pair_changed[i];
862  return success;
863 }
864 
865 
866 /*****************************************************************************/
867 /* liveness marking, Ligature3s */
868 
870  StringAccum sa;
871  sa << '[' << m.code_name(in1) << ' ' << m.code_name(in2)
872  << " -> " << m.code_name(out) << ']';
873  return sa.take_string();
874 }
875 
876 inline bool
877 operator<(const Metrics::Ligature3 &l1, const Metrics::Ligature3 &l2)
878 {
879  // topological < : is l1's output one of l2's inputs?
880  if (l1.out == l2.in1 || l1.out == l2.in2)
881  return true;
882  else
883  return l1.in1 < l2.in1
884  || (l1.in1 == l2.in1 && (l1.in2 < l2.in2
885  || (l1.in2 == l2.in2 && l1.out < l2.out)));
886 }
887 
888 void
890 {
891  /* Develop a topologically-sorted ligature list. */
892  all_ligs.clear();
893  for (Code code = 0; code < _encoding.size(); code++)
894  for (const Ligature *l = _encoding[code].ligatures.begin(); l != _encoding[code].ligatures.end(); l++)
895  all_ligs.push_back(Ligature3(code, l->in2, l->out));
896  std::sort(all_ligs.begin(), all_ligs.end());
897 }
898 
899 void
901 {
902  _liveness_marked = true;
903  bool changed;
904 
905  // make sure we have ligatures
906  Vector<Ligature3> my_ligs;
907  if (!all_ligs) {
908  all_ligatures(my_ligs);
909  all_ligs = &my_ligs;
910  }
911 
912  /* Characters below 'size' are in both virtual and base encodings. */
913  for (Char *ch = _encoding.begin(); ch < _encoding.begin() + size; ch++)
914  if (ch->visible())
915  ch->flags |= Char::LIVE | (ch->virtual_char ? 0 : Char::BASE_LIVE);
916 
917  /* Characters reachable from live chars by live ligatures are live. */
918  redo_live_reachable:
919  for (const Ligature3 *l = all_ligs->begin(); l != all_ligs->end(); l++)
920  if (_encoding[l->in1].flag(Char::LIVE) && _encoding[l->in2].flag(Char::LIVE)) {
921  Char &ch = _encoding[l->out];
922  if (!ch.flag(Char::LIVE))
923  ch.flags |= Char::LIVE | Char::CONTEXT_ONLY | (ch.virtual_char ? 0 : Char::BASE_LIVE);
924  if (ch.flag(Char::CONTEXT_ONLY) && !ch.context_setting(l->in1, l->in2))
925  ch.flags &= ~Char::CONTEXT_ONLY;
926  }
927 
928  /* Characters reachable from context-only ligatures are live. */
929  changed = false;
930  for (Char *ch = _encoding.begin(); ch != _encoding.end(); ch++)
931  if (ch->flag(Char::CONTEXT_ONLY)) {
932  Char &ch1 = _encoding[ch->built_in1];
933  Char &ch2 = _encoding[ch->built_in2];
934  if (!ch1.flag(Char::LIVE) || !ch2.flag(Char::LIVE)) {
935  ch1.flags |= Char::LIVE;
936  ch2.flags |= Char::LIVE;
937  changed = true;
938  }
939  }
940  if (changed)
941  goto redo_live_reachable;
942 
943  /* Characters reachable from live settings are base-live. */
944  for (Char *ch = _encoding.begin(); ch != _encoding.end(); ch++)
945  if (ch->flag(Char::LIVE))
946  if (VirtualChar *vc = ch->virtual_char) {
947  int font_number = 0;
948  for (Setting *s = vc->setting.begin(); s != vc->setting.end(); s++)
949  if (s->op == Setting::SHOW && font_number == 0
950  && _encoding[s->x].base_code >= 0)
951  _encoding[s->x].flags |= Char::BASE_LIVE;
952  else if (s->op == Setting::FONT)
953  font_number = s->x;
954  }
955 }
956 
957 void
958 Metrics::reencode(const Vector<Code> &reencoding)
959 {
960  for (Char *ch = _encoding.begin(); ch != _encoding.end(); ch++) {
961  for (Ligature *l = ch->ligatures.begin(); l != ch->ligatures.end(); l++) {
962  l->in2 = reencoding[l->in2];
963  l->out = reencoding[l->out];
964  }
965  for (Kern *k = ch->kerns.begin(); k != ch->kerns.end(); k++)
966  k->in2 = reencoding[k->in2];
967  if (VirtualChar *vc = ch->virtual_char) {
968  int font_number = 0;
969  for (Setting *s = vc->setting.begin(); s != vc->setting.end(); s++)
970  if (s->op == Setting::SHOW && font_number == 0)
971  s->x = reencoding[s->x];
972  else if (s->op == Setting::FONT)
973  font_number = s->x;
974  }
975  if (ch->built_in1 >= 0) {
976  ch->built_in1 = reencoding[ch->built_in1];
977  ch->built_in2 = reencoding[ch->built_in2];
978  }
979  if (ch->base_code >= 0)
980  ch->base_code = reencoding[ch->base_code];
981  }
982  _emap.clear();
983 }
984 
985 
986 /*****************************************************************************/
987 /* shrinking the encoding */
988 
989 bool
991 {
992  // return true iff this character could represent the context setting of
993  // 'in1' and 'in2'
994  if (!virtual_char || ligatures.size())
995  return false;
996  else
997  return (in1 == built_in1 || in2 == built_in2);
998 }
999 
1000 void
1002 {
1003  /* Function makes it so that characters below 'size' do not point to
1004  characters above 'size', except for context ligatures. */
1005 
1006  /* Change "emptyslot"s to ".notdef"s. */
1007  for (Char *ch = _encoding.begin(); ch != _encoding.end(); ch++)
1008  if (ch->glyph == emptyslot_glyph()) {
1009  ch->glyph = 0;
1010  ch->base_code = -1;
1011  // 21.Feb.2007: Character isn't live any more.
1012  ch->flags &= ~(Char::BASE_LIVE | Char::LIVE);
1013  }
1014 
1015  /* Maybe we don't need to do anything else. */
1016  if (_encoding.size() <= size) {
1017  _encoding.resize(size, Char());
1018  return;
1019  }
1020 
1021  /* Need liveness markings. */
1022  if (!_liveness_marked)
1024 
1025  /* Characters below 'size' are 'good'.
1026  Characters above 'size' are not 'good'. */
1027  Vector<int> good(_encoding.size(), 1);
1028  for (Code c = size; c < _encoding.size(); c++)
1029  good[c] = 0;
1030 
1031  /* Characters encoded via base_code are 'good', though. */
1032  for (Char *ch = _encoding.begin(); ch < _encoding.begin() + size; ch++)
1033  if (ch->base_code >= size)
1034  good[ch->base_code] = 1;
1035 
1036  /* Some fake characters might point beyond 'size'; remove them too. No
1037  need for a multipass algorithm since virtual chars never point to
1038  virtual chars. */
1039  for (Code c = 0; c < _encoding.size(); c++) {
1040  if (VirtualChar *vc = _encoding[c].virtual_char) {
1041  int font_number = 0;
1042  for (Setting *s = vc->setting.begin(); s != vc->setting.end(); s++)
1043  if (s->op == Setting::SHOW && font_number == 0 && !good[s->x]) {
1044  _encoding[c].clear();
1045  goto bad_virtual_char;
1046  } else if (s->op == Setting::FONT)
1047  font_number = s->x;
1048  }
1049  if (c < size)
1050  good[c] = 1;
1051  bad_virtual_char: ;
1052  }
1053 
1054  /* Certainly none of the later ligatures or kerns will be meaningful. */
1055  for (Code c = size; c < _encoding.size(); c++) {
1056  _encoding[c].ligatures.clear();
1057  _encoding[c].kerns.clear();
1058  }
1059 
1060  /* Remove ligatures and kerns that point beyond 'size', except for valid
1061  context ligatures. Also remove ligatures that have non-live
1062  components. */
1063  /* 30.May.2005 -- Kerns might point involve a too-high character; kill
1064  them. */
1065  for (Code c = 0; c < size; c++) {
1066  Char &ch = _encoding[c];
1067  for (Ligature *l = ch.ligatures.begin(); l != ch.ligatures.end(); l++)
1068  if (!good[l->in2] || l->in2 >= size
1069  || (!good[l->out] && !_encoding[l->out].context_setting(c, l->in2))) {
1070  *l = ch.ligatures.back();
1071  ch.ligatures.pop_back();
1072  l--;
1073  }
1074  for (Kern *k = ch.kerns.begin(); k != ch.kerns.end(); k++)
1075  if (!good[k->in2] || k->in2 >= size) {
1076  *k = ch.kerns.back();
1077  ch.kerns.pop_back();
1078  k--;
1079  }
1080  }
1081 
1082  /* We are done! */
1083 }
1084 
1085 namespace {
1086 // preference-sorting extra characters
1087 enum {
1088  CONVENTIONAL_F_LIGATURE_SCORE = 4,
1089  CONVENTIONAL_F_F_LIGATURE_SCORE = 5,
1090  BASIC_LATIN_LOWER_SCORE = 3,
1091  BASIC_LATIN_UPPER_SCORE = 4,
1092  BASIC_LATIN_OTHER_SCORE = 5,
1093  LATIN1_SUPPLEMENT_SCORE = 6,
1094  LOW_16_SCORE = 7,
1095  OTHER_SCORE = 8,
1096  NOCHAR_SCORE = 100000,
1097  CONTEXT_PENALTY = 4
1098 };
1099 
1100 static int
1101 unicode_score(uint32_t u)
1102 {
1103  if (u == 0)
1104  return NOCHAR_SCORE;
1105  else if (u >= 'a' && u <= 'z')
1106  return BASIC_LATIN_LOWER_SCORE;
1107  else if (u >= 'A' && u <= 'Z')
1108  return BASIC_LATIN_UPPER_SCORE;
1109  else if (u < 0x0080)
1110  return BASIC_LATIN_OTHER_SCORE;
1111  else if (u < 0x0100)
1112  return LATIN1_SUPPLEMENT_SCORE;
1113  else if (u < 0x8000)
1114  return LOW_16_SCORE;
1115  else
1116  return OTHER_SCORE;
1117 }
1118 
1119 struct Slot {
1120  Metrics::Code old_code;
1121  Metrics::Code new_code;
1123  int score;
1124  int lookup_source;
1125 };
1126 
1127 inline bool
1128 operator<(const Slot &a, const Slot &b)
1129 {
1130  // note: will give real glyphs priority over virtual ones at a given
1131  // priority
1132  // 6.Jul.2014 -- Make sure you include an old_code comparison; this
1133  // is required to ensure that a ligature's inputs (which have smaller
1134  // old_codes) are included whenever its outputs are included.
1135  if (a.lookup_source != b.lookup_source)
1136  return a.lookup_source < b.lookup_source;
1137  if (a.score != b.score)
1138  return a.score < b.score;
1139  if (a.glyph != b.glyph)
1140  return a.glyph < b.glyph;
1141  return a.old_code < b.old_code;
1142 }
1143 }
1144 
1145 void
1147 {
1148  /* Move characters around. */
1149 
1150  /* Maybe we don't need to do anything. */
1151  if (_encoding.size() <= size) {
1152  cut_encoding(size);
1153  return;
1154  }
1155 
1156  /* Need a list of all ligatures.. */
1157  Vector<Ligature3> all_ligs;
1158  all_ligatures(all_ligs);
1159 
1160  /* Need liveness markings. */
1161  if (!_liveness_marked)
1162  mark_liveness(size, &all_ligs);
1163 
1164  /* Score characters by importance. Importance relates first to Unicode
1165  values, and then recursively to the importances of characters that form
1166  a ligature. */
1167 
1168  /* Create an initial set of scores, based on Unicode values. */
1169  Vector<int> scores(_encoding.size(), NOCHAR_SCORE);
1170  for (int i = 0; i < _encoding.size(); i++)
1171  if (_encoding[i].unicode)
1172  scores[i] = unicode_score(_encoding[i].unicode);
1173 
1174  /* Prefer conventional f-ligatures. */
1175  bool has_ff = false;
1176  for (Ligature3* l = all_ligs.begin(); l != all_ligs.end(); ++l)
1177  if (_encoding[l->in1].unicode == 'f'
1178  && (_encoding[l->in2].unicode == 'f'
1179  || _encoding[l->in2].unicode == 'i'
1180  || _encoding[l->in2].unicode == 'l')) {
1181  if (scores[l->out] > CONVENTIONAL_F_LIGATURE_SCORE)
1182  scores[l->out] = CONVENTIONAL_F_LIGATURE_SCORE;
1183  if (_encoding[l->in2].unicode == 'f') {
1184  _encoding[l->out].flags |= Char::IS_FF;
1185  has_ff = true;
1186  }
1187  }
1188  if (has_ff)
1189  for (Ligature3* l = all_ligs.begin(); l != all_ligs.end(); ++l)
1190  if (_encoding[l->in1].flag(Char::IS_FF)
1191  && (_encoding[l->in2].unicode == 'i'
1192  || _encoding[l->in2].unicode == 'l')
1193  && scores[l->out] > CONVENTIONAL_F_F_LIGATURE_SCORE)
1194  scores[l->out] = CONVENTIONAL_F_F_LIGATURE_SCORE;
1195 
1196  /* Repeat these steps until you reach a stable set of scores: Score
1197  ligatures (ligscore = SUM[char scores]), then score characters touched
1198  only by fakes. */
1199  bool changed = true;
1200  while (changed) {
1201  changed = false;
1202  for (Ligature3 *l = all_ligs.begin(); l != all_ligs.end(); l++) {
1203  int score = scores[l->in1] + scores[l->in2];
1204  if (scores[l->out] > score)
1205  scores[l->out] = score, changed = true;
1206  }
1207 
1208  for (Code c = 0; c < _encoding.size(); c++)
1209  if (VirtualChar *vc = _encoding[c].virtual_char) {
1210  /* Make sure that if this virtual character appears, its parts
1211  will also appear, by scoring the parts less */
1212  int score = scores[c] - 1, font_number = 0;
1213  for (Setting *s = vc->setting.begin(); s != vc->setting.end(); s++)
1214  if (s->op == Setting::SHOW && font_number == 0
1215  && score < scores[s->x])
1216  scores[s->x] = score, changed = true;
1217  else if (s->op == Setting::FONT)
1218  font_number = s->x;
1219  }
1220  }
1221 
1222  /* Rescore intermediates to not be better off than their endpoints. */
1223  /* XXX multiple layers of intermediate? */
1224  for (Code c = 0; c < _encoding.size(); c++) {
1225  Char &ch = _encoding[c];
1226  if (ch.flag(Char::INTERMEDIATE))
1227  for (Ligature *l = ch.ligatures.begin(); l != ch.ligatures.end(); l++)
1228  if (scores[c] < scores[l->out] && !_encoding[l->out].context_setting(c, l->in2))
1229  scores[c] = scores[l->out];
1230  }
1231 
1232  /* Collect characters that want to be reassigned. */
1233  Vector<Slot> slots;
1234  for (Code c = size; c < _encoding.size(); c++)
1235  if (scores[c] < NOCHAR_SCORE
1237  && (_encoding[c].flags & (Char::LIVE | Char::BASE_LIVE))) {
1238  Slot slot = { c, -1, _encoding[c].glyph, scores[c], _encoding[c].lookup_source };
1239  slots.push_back(slot);
1240  }
1241  // Sort them by score, then by glyph.
1242  std::sort(slots.begin(), slots.end());
1243 
1244  /* Prefer their old slots, if available. */
1245  for (Slot *slot = slots.begin(); slot < slots.end(); slot++)
1246  if (PermString g = code_name(slot->old_code)) {
1247  int c = dvipsenc.encoding_of(g);
1248  if (c >= 0 && _encoding[c].glyph == 0) {
1249  _encoding[c].swap(_encoding[slot->old_code]);
1250  slot->new_code = c;
1251  }
1252  }
1253 
1254  /* List empty slots in two phases: Those not encoded by the input
1255  encoding, then those encoded by the input encoding (but that character
1256  wasn't available). */
1257  Vector<Code> empty_codes;
1258  for (int want_encoded = 0; want_encoded < 2; want_encoded++)
1259  for (Code c = 0; c < size; c++)
1260  if (_encoding[c].base_code < 0
1261  && dvipsenc.encoded(c) == (bool) want_encoded)
1262  empty_codes.push_back(c);
1263 
1264  /* Then, assign codes to the unencoded characters. */
1265  int nunencoded = 0;
1266 
1267  for (Slot *slot = slots.begin(); slot != slots.end(); slot++) {
1268  if (slot->new_code >= 0)
1269  continue;
1270 
1271  int needs = (_encoding[slot->old_code].visible_base() ? 1 : 0)
1272  + (_encoding[slot->old_code].flag(Char::LIVE) ? 2 : 0);
1273  assert(needs > 0);
1274 
1275  Code dest = -1;
1276  for (Code *h = empty_codes.begin(); h < empty_codes.end() && dest < 0; h++) {
1277  int haves = (_encoding[*h].base_code < 0 ? 1 : 0)
1278  + (!_encoding[*h].visible() ? 2 : 0);
1279  if ((needs & haves) == needs)
1280  dest = *h;
1281  }
1282 
1283  if (dest >= 0) {
1284  if (needs & 2) {
1286  _encoding[dest].swap(_encoding[slot->old_code]);
1287  slot->new_code = dest;
1288  } else {
1289  _encoding[slot->old_code].base_code = dest;
1290  slot->new_code = slot->old_code;
1291  }
1292  if (needs & 1) {
1293  assert(_encoding[dest].base_code < 0 || _encoding[dest].base_code == slot->old_code);
1294  _encoding[dest].base_code = slot->old_code;
1295  }
1296  } else
1297  nunencoded++;
1298  }
1299 
1300  /* Complain if some characters can't fit. */
1301  if (nunencoded) {
1302  // collect names of unencoded glyphs
1303  Vector<String> unencoded;
1304  for (Slot *slot = slots.begin(); slot != slots.end(); slot++)
1305  if (slot->new_code < 0)
1306  unencoded.push_back(code_name(slot->old_code));
1307  std::sort(unencoded.begin(), unencoded.end());
1308  StringAccum sa;
1309  for (const String* a = unencoded.begin(); a < unencoded.end(); a++)
1310  sa << *a << ' ';
1311  sa.pop_back();
1312  sa.append_break_lines(sa.take_string(), 68, " ");
1313  sa.pop_back();
1314  errh->lwarning(" ", (unencoded.size() == 1 ? "not enough room in encoding, ignoring %d glyph" : "not enough room in encoding, ignoring %d glyphs"), unencoded.size());
1315  errh->lmessage(" ", "(\
1316 The font uses more glyphs than the encoding has available slots,\n\
1317 so these glyphs have been left out:\n%s\n\
1318 To select specific glyphs, add them to the input encoding.)", sa.c_str());
1319  }
1320 
1321  /* Reencode changed slots. */
1322  Vector<Code> reencoding;
1323  for (Code c = 0; c < _encoding.size(); c++)
1324  reencoding.push_back(c);
1325  for (Slot *s = slots.begin(); s != slots.end(); s++)
1326  if (s->new_code >= 0)
1327  reencoding[s->old_code] = s->new_code;
1328  reencode(reencoding);
1329 
1330  check();
1331 }
1332 
1333 void
1335 {
1336  Vector<Code> reencoding;
1337  for (Code c = 0; c < size && c < _encoding.size(); c++) {
1338  Char &ch = _encoding[c];
1339  if (ch.base_code >= 0 && ch.base_code != c) {
1340  if (!reencoding.size())
1341  for (Code cc = 0; cc < _encoding.size(); cc++)
1342  reencoding.push_back(cc);
1343  reencoding[ch.base_code] = c;
1344  reencoding[c] = ch.base_code;
1345  _encoding[c].swap(_encoding[ch.base_code]);
1346  }
1347  if (ch.virtual_char) // remove it
1348  ch.clear();
1349  }
1350  if (reencoding.size()) {
1351  reencode(reencoding);
1352  cut_encoding(size);
1353  }
1354  check();
1355 }
1356 
1357 
1358 /*****************************************************************************/
1359 /* output */
1360 
1361 bool
1363 {
1364  if (size > _encoding.size())
1365  size = _encoding.size();
1366  for (const Char *ch = _encoding.begin(); ch < _encoding.begin() + size; ch++)
1367  if (ch->glyph /* actually encoded */
1368  && (ch->pdx || ch->pdy || ch->adx || ch->virtual_char))
1369  return true;
1370  return false;
1371 }
1372 
1373 bool
1375 {
1376  if (!_liveness_marked)
1377  mark_liveness(_encoding.size());
1378  for (const Char *ch = _encoding.begin(); ch < _encoding.end(); ch++)
1379  if ((ch->flags & Char::BASE_LIVE) && ch->glyph != _boundary_glyph)
1380  return true;
1381  return false;
1382 }
1383 
1384 bool
1386 {
1387  extern int letterspace;
1388 
1389  if (!(sm & SET_KEEP))
1390  v.clear();
1391 
1392  if (!valid_code(code) || _encoding[code].glyph == 0)
1393  return false;
1394 
1395  const Char &ch = _encoding[code];
1396 
1397  if (const VirtualChar *vc = ch.virtual_char) {
1398  bool good = true;
1399  int font_number = 0;
1400 
1401  if (ch.pdx != 0 || ch.pdy != 0)
1402  v.push_back(Setting(Setting::MOVE, ch.pdx, ch.pdy));
1403 
1404  for (const Setting *s = vc->setting.begin(); s != vc->setting.end(); s++)
1405  switch (s->op) {
1406  case Setting::MOVE:
1407  case Setting::RULE:
1408  case Setting::PUSH:
1409  case Setting::POP:
1410  case Setting::SPECIAL:
1411  v.push_back(*s);
1412  break;
1413  case Setting::FONT:
1414  v.push_back(*s);
1415  font_number = s->x;
1416  break;
1417  case Setting::SHOW:
1418  if (font_number == 0)
1419  good &= setting(s->x, v, (SettingMode)(sm | SET_KEEP));
1420  else
1421  v.push_back(*s);
1422  break;
1423  case Setting::KERN:
1424  case Setting::KERNX:
1425  if (sm & SET_INTERMEDIATE)
1426  v.push_back(*s);
1427  else if (font_number == 0 && s > vc->setting.begin()
1428  && s + 1 < vc->setting.end()
1429  && s[-1].op == Setting::SHOW
1430  && s[1].op == Setting::SHOW) {
1431  int k = kern(s[-1].x, s[1].x);
1432  if (s->op == Setting::KERNX)
1433  k -= letterspace;
1434  if (k)
1435  v.push_back(Setting(Setting::MOVE, k, 0));
1436  }
1437  break;
1438  }
1439 
1440  if (ch.pdy != 0 || ch.adx - ch.pdx != 0)
1441  v.push_back(Setting(Setting::MOVE, ch.adx - ch.pdx, -ch.pdy));
1442  return good;
1443 
1444  } else if (ch.base_code >= 0) {
1445  if (ch.pdx != 0 || ch.pdy != 0)
1446  v.push_back(Setting(Setting::MOVE, ch.pdx, ch.pdy));
1447 
1448  v.push_back(Setting(Setting::SHOW, ch.base_code, ch.glyph));
1449 
1450  if (ch.pdy != 0 || ch.adx - ch.pdx != 0)
1451  v.push_back(Setting(Setting::MOVE, ch.adx - ch.pdx, -ch.pdy));
1452  return true;
1453 
1454  } else
1455  return false;
1456 }
1457 
1458 int
1460 {
1461  in2.clear();
1462  out.clear();
1463  context.clear();
1464 
1465  const Char &in1ch = _encoding[in1];
1466  for (const Ligature *l = in1ch.ligatures.begin(); l != in1ch.ligatures.end(); l++) {
1467  in2.push_back(l->in2);
1468  const Char &outch = _encoding[l->out];
1469  if (outch.context_setting(in1, l->in2)) {
1470  if (in1 == outch.built_in1 && l->in2 == outch.built_in2)
1471  in2.pop_back();
1472  else if (in1 == outch.built_in1) {
1473  out.push_back(outch.built_in2);
1474  context.push_back(-1);
1475  } else {
1476  out.push_back(outch.built_in1);
1477  context.push_back(1);
1478  }
1479  } else {
1480  out.push_back(l->out);
1481  context.push_back(0);
1482  }
1483  }
1484 
1485  return in2.size();
1486 }
1487 
1488 int
1490 {
1491  in2.clear();
1492  kern.clear();
1493 
1494  const Char &in1ch = _encoding[in1];
1495  for (const Kern *k = in1ch.kerns.begin(); k != in1ch.kerns.end(); k++)
1496  if (k->kern != 0) {
1497  in2.push_back(k->in2);
1498  kern.push_back(k->kern);
1499  }
1500 
1501  return in2.size();
1502 }
1503 
1504 
1505 /*****************************************************************************/
1506 /* debugging */
1507 
1508 void
1509 Metrics::unparse(const Char *ch) const
1510 {
1511  Code c;
1512  if (ch >= _encoding.begin() && ch < _encoding.end())
1513  c = ch - _encoding.begin();
1514  else
1515  c = -1;
1516  fprintf(stderr, "%4d/%s%s%s%s%s%s\n", c, code_str(c),
1517  (ch->flag(Char::LIVE) ? " [L]" : ""),
1518  (ch->flag(Char::BASE_LIVE) ? " [B]" : ""),
1519  (ch->flag(Char::CONTEXT_ONLY) ? " [C]" : ""),
1520  (ch->flag(Char::BUILT) ? " [!]" : ""),
1521  (ch->base_code >= 0 ? " <BC>" : ""));
1522  if (ch->base_code >= 0 && ch->base_code != c)
1523  fprintf(stderr, "\tBASE %d/%s\n", ch->base_code, code_str(ch->base_code));
1524  if (const VirtualChar *vc = ch->virtual_char) {
1525  fprintf(stderr, "\t*");
1526  int curfont = 0;
1527  for (const Setting *s = vc->setting.begin(); s != vc->setting.end(); s++)
1528  switch (s->op) {
1529  case Setting::FONT:
1530  fprintf(stderr, " {F%d}", s->x);
1531  curfont = s->x;
1532  break;
1533  case Setting::SHOW:
1534  fprintf(stderr, " %d", s->x);
1535  if (curfont == 0)
1536  fprintf(stderr, "/%s", code_str(s->x));
1537  break;
1538  case Setting::KERN:
1539  fprintf(stderr, " <>");
1540  break;
1541  case Setting::MOVE:
1542  fprintf(stderr, " <%+d,%+d>", s->x, s->y);
1543  break;
1544  case Setting::RULE:
1545  fprintf(stderr, " [%d,%d]", s->x, s->y);
1546  break;
1547  case Setting::PUSH:
1548  fprintf(stderr, " (");
1549  break;
1550  case Setting::POP:
1551  fprintf(stderr, " )");
1552  break;
1553  case Setting::SPECIAL:
1554  fprintf(stderr, " S{%s}", s->s.c_str());
1555  break;
1556  }
1557  fprintf(stderr, " ((%d/%s, %d/%s))\n", ch->built_in1, code_str(ch->built_in1), ch->built_in2, code_str(ch->built_in2));
1558  }
1559  for (const Ligature *l = ch->ligatures.begin(); l != ch->ligatures.end(); l++)
1560  fprintf(stderr, "\t[%d/%s => %d/%s]%s\n", l->in2, code_str(l->in2), l->out, code_str(l->out), (_encoding[l->out].context_setting(c, l->in2) ? " [C]" : ""));
1561 #if 0
1562  for (const Kern *k = ch->kerns.begin(); k != ch->kerns.end(); k++)
1563  fprintf(stderr, "\t{%d/%s %+d}\n", k->in2, code_str(k->in2), k->kern);
1564 #endif
1565 }
1566 
1567 void
1569 {
1570  for (const Char *ch = _encoding.begin(); ch < _encoding.end(); ch++)
1571  if (ch->glyph)
1572  unparse(ch);
1573 }
int nglyphs
Definition: afm2pl.c:208
int code
Definition: aftopl.c:52
#define name
int encoding_of(PermString) const
PermString encoding(int e) const
bool encoded(int e) const
Error reporting class.
Definition: error.hh:86
void lmessage(const String &landmark, const char *fmt,...)
Print an informational message with a landmark annotation.
Definition: error.cc:848
int lwarning(const String &landmark, const char *fmt,...)
Print a warning message with a landmark annotation.
Definition: error.cc:858
bool allow_substitution(Efont::OpenType::Glyph glyph, const Vector< PermString > &glyph_names, uint32_t unicode) const
Definition: glyphfilter.hh:60
bool allow_alternate(Efont::OpenType::Glyph glyph, const Vector< PermString > &glyph_names, uint32_t unicode) const
Definition: glyphfilter.hh:66
bool pair_allowed(Code, Code) const
Definition: metrics.cc:533
void disallow_pair(Code, Code)
Definition: metrics.cc:563
static bool bit(const Vector< uint32_t > &, Code)
Definition: metrics.cc:513
bool allowed(Code, bool left_context) const
Definition: metrics.cc:522
ChangedContext(const ChangedContext &)
ChangedContext(int ncodes)
Definition: metrics.cc:493
void ensure_all(Code) const
Definition: metrics.cc:506
bool virgin(Code) const
Definition: metrics.cc:545
Vector< uint32_t > _all_sentinel
Definition: metrics.cc:486
Metrics::Code Code
Definition: metrics.cc:475
Vector< Vector< uint32_t > * > _v
Definition: metrics.cc:484
ChangedContext & operator=(const ChangedContext &)
Vector< int > _emap
Definition: metrics.hh:146
int kern(Code in1, Code in2) const
Definition: metrics.cc:379
Code base_code(Code) const
Definition: metrics.hh:241
void apply_single(Code cin, const Substitution *s, int lookup, ChangedContext &ctx, const GlyphFilter &glyph_filter, const Vector< PermString > &glyph_names)
Definition: metrics.cc:582
Code encoding(Glyph g, Code after) const
Definition: metrics.hh:250
const Efont::CharstringProgram * mapped_font(int i) const
Definition: metrics.hh:35
void encode(Code code, uint32_t uni, Glyph g)
Definition: metrics.cc:159
bool nonvirtual_code(Code) const
Definition: metrics.hh:208
bool next_encoding(Vector< Code > &codes, const Vector< Glyph > &glyphs) const
Definition: metrics.cc:701
SettingMode
Definition: metrics.hh:83
@ SET_INTERMEDIATE
Definition: metrics.hh:83
@ SET_KEEP
Definition: metrics.hh:83
Vector< Kern > _altselectors
Definition: metrics.hh:151
uint32_t unicode(Code code) const
Definition: metrics.hh:223
Kern * kern_obj(Code, Code)
Definition: metrics.cc:368
void all_ligatures(Vector< Ligature3 > &) const
Definition: metrics.cc:889
Code hard_encoding(Glyph, Code) const
Definition: metrics.cc:124
int Code
Definition: metrics.hh:12
Ligature * ligature_obj(Code, Code)
Definition: metrics.cc:283
Glyph _boundary_glyph
Definition: metrics.hh:148
void shrink_encoding(int size, const DvipsEncoding &, ErrorHandler *)
Definition: metrics.cc:1146
Metrics(const Efont::CharstringProgram *, int nglyphs)
Definition: metrics.cc:26
~Metrics()
Definition: metrics.cc:35
void apply_base_encoding(const String &font_name, const DvipsEncoding &, const Vector< int > &mapping)
Definition: metrics.cc:195
bool _liveness_marked
Definition: metrics.hh:157
Code unicode_encoding(uint32_t uni) const
Definition: metrics.cc:115
friend bool operator<(const Ligature3 &, const Ligature3 &)
Definition: metrics.cc:877
void new_ligature(Code, Code, Code)
Definition: metrics.cc:294
void apply_alternates_single(Code cin, const Substitution *s, int lookup, const GlyphFilter &glyph_filter, const Vector< PermString > &glyph_names)
Definition: metrics.cc:751
void apply_simple_context_ligature(const Vector< Code > &codes, const Substitution *s, int lookup, ChangedContext &ctx, const GlyphFilter &glyph_filter, const Vector< PermString > &glyph_names)
Definition: metrics.cc:669
void mark_liveness(int size, const Vector< Ligature3 > *=0)
Definition: metrics.cc:900
Glyph glyph(Code code) const
Definition: metrics.hh:214
Vector< const Efont::CharstringProgram * > _mapped_fonts
Definition: metrics.hh:159
int kerns(Code in1, Vector< Code > &in2, Vector< int > &kern) const
Definition: metrics.cc:1489
void set_kern(Code in1, Code in2, int kern)
Definition: metrics.cc:399
void apply_alternates_ligature(const Vector< Code > &codes, const Substitution *s, int lookup, const GlyphFilter &glyph_filter, const Vector< PermString > &glyph_names)
Definition: metrics.cc:772
int add_mapped_font(const Efont::CharstringProgram *, const String &)
Definition: metrics.cc:42
void encode_virtual(Code, PermString, uint32_t uni, const Vector< Setting > &, bool base_char)
Definition: metrics.cc:173
void add_altselector_code(Code, int altselector_type)
Definition: metrics.cc:214
Code pair_code(Code, Code, int lookup_source=-1)
Definition: metrics.cc:322
void add_ligature(Code in1, Code in2, Code out)
Definition: metrics.cc:307
int ligatures(Code in1, Vector< Code > &in2, Vector< Code > &out, Vector< int > &context) const
Definition: metrics.cc:1459
void unparse() const
Definition: metrics.cc:1568
PermString code_name(Code) const
Definition: metrics.cc:91
bool setting(Code, Vector< Setting > &, SettingMode=SET_NONE) const
Definition: metrics.cc:1385
void repoint_ligature(Code, Ligature *, Code)
Definition: metrics.cc:301
void add_single_positioning(Code, int pdx, int pdy, int adx)
Definition: metrics.cc:459
void check() const
Definition: metrics.cc:50
void remove_ligatures(Code in1, Code in2)
Definition: metrics.cc:347
void apply_alternates(const Vector< Substitution > &, int lookup, const GlyphFilter &, const Vector< PermString > &glyph_names)
Definition: metrics.cc:791
bool valid_code(Code) const
Definition: metrics.hh:202
int reencode_right_ligkern(Code old_in2, Code new_in2)
Definition: metrics.cc:421
void apply_ligature(const Vector< Code > &, const Substitution *, int lookup)
Definition: metrics.cc:628
Vector< String > _mapped_font_names
Definition: metrics.hh:160
void add_kern(Code in1, Code in2, int kern)
Definition: metrics.cc:390
@ CODE_ALL
Definition: metrics.hh:67
Efont::OpenType::Glyph Glyph
Definition: metrics.hh:13
void assign_emap(Glyph, Code)
Definition: metrics.hh:260
void make_base(int size)
Definition: metrics.cc:1334
void cut_encoding(int size)
Definition: metrics.cc:1001
bool base_glyphs(Vector< Glyph > &, int size) const
Definition: metrics.cc:225
Glyph emptyslot_glyph() const
Definition: metrics.hh:25
void reencode(const Vector< Code > &)
Definition: metrics.cc:958
int apply(const Vector< Substitution > &, bool allow_single, int lookup, const GlyphFilter &, const Vector< PermString > &glyph_names)
Definition: metrics.cc:720
bool need_base()
Definition: metrics.cc:1374
const char * code_str(Code) const
Definition: metrics.hh:268
Code force_encoding(Glyph g, int lookup_source=-1)
Definition: metrics.cc:141
bool need_virtual(int size) const
Definition: metrics.cc:1362
@ VIRTUAL_GLYPH
Definition: metrics.hh:14
Glyph _emptyslot_glyph
Definition: metrics.hh:149
Efficiently build up Strings from pieces.
Definition: straccum.hh:21
String take_string()
Return a String object with this StringAccum's contents.
Definition: straccum.cc:197
const char * c_str()
Null-terminate this StringAccum and return its data.
Definition: straccum.cc:122
void append_break_lines(const String &text, int linelen, const String &leftmargin=String())
Definition: straccum.cc:280
void pop_back(int n=1)
Remove characters from the end of the StringAccum.
Definition: straccum.hh:444
Definition: vector.hh:17
void clear()
Definition: vector.hh:87
iterator begin()
Definition: vector.hh:48
Vector< T > & assign(size_type n, const T &e=T())
Definition: vector.cc:65
void push_back(const T &x)
Definition: vector.hh:102
void resize(size_type nn, const T &e=T())
Definition: vector.cc:166
size_type size() const
Definition: vector.hh:54
void pop_back()
Definition: vector.hh:115
iterator end()
Definition: vector.hh:50
#define n
Definition: t4ht.c:1290
#define b
Definition: jpegint.h:372
void glyphs(int opcode)
Definition: disdvi.c:775
int v
Definition: dviconv.c:10
int h
Definition: dviconv.c:9
#define s
Definition: afcover.h:80
short nleft
Definition: globals.h:117
#define c(n)
Definition: gpos-common.c:150
#define a(n)
Definition: gpos-common.c:148
FILE * out
Definition: hbf2gf.c:286
assert(pcxLoadImage24((char *)((void *) 0), fp, pinfo, hdr))
char String
Definition: tttypes.h:35
small capitals from c petite p scientific f u
Definition: afcover.h:88
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
#define false
Definition: ftrandom.c:52
@ right
Definition: annotate.c:15
unsigned int uint32_t
Definition: stdint.h:80
#define fprintf
Definition: mendex.h:64
#define dest
char * as
Definition: fixwrites.c:8
float x
Definition: cordic.py:15
static bool assign_bitvec(int *&bitvec, int e, int n)
Definition: metrics.cc:815
int letterspace
Definition: otftotfm.cc:279
int k
Definition: otp-parser.c:70
#define Char
Definition: p2c.h:237
boolean changed
Definition: parse_ofm.c:90
unsigned char bit
Definition: pbm.h:9
PermString permprintf(const char *format,...)
Definition: permstr.cc:298
struct const_name font_name[]
Definition: picttoppm.c:492
static int32_t last
Definition: ppagelist.c:29
static int size
Definition: ppmlabel.c:24
int g
Definition: ppmqvga.c:68
#define visible
Definition: prepmx.c:89
bstring c int memset(void *s, int c, int length)
#define flags
slotref slot
Definition: opcodes.h:237
static ErrorHandler * errh
Definition: main.cc:71
static int sort(lua_State *L)
Definition: ltablib.c:411
#define swap(sp)
Definition: interp.c:123
#define flag
Definition: round_prec.c:45
ShellFileEnvironment e
Definition: sh6.c:388
static FILE * in
Definition: squeeze.c:36
Click's StringAccum class, used to construct Strings efficiently from pieces.
Code built_in1
Definition: metrics.hh:128
bool flag(int f) const
Definition: metrics.hh:140
void clear()
Definition: metrics.cc:242
Vector< Ligature > ligatures
Definition: metrics.hh:122
Code built_in2
Definition: metrics.hh:129
int lookup_source
Definition: metrics.hh:130
uint32_t unicode
Definition: metrics.hh:121
Vector< Kern > kerns
Definition: metrics.hh:123
bool context_setting(Code in1, Code in2) const
Definition: metrics.cc:990
VirtualChar * virtual_char
Definition: metrics.hh:124
Code base_code
Definition: metrics.hh:120
void swap(Char &)
Definition: metrics.cc:258
String unparse(const Metrics &m) const
Definition: metrics.cc:869
PermString name
Definition: metrics.hh:104
Vector< Setting > setting
Definition: metrics.hh:105
@ FONT
Definition: setting.hh:6
@ KERNX
Definition: setting.hh:6
@ MOVE
Definition: setting.hh:6
@ KERN
Definition: setting.hh:6
@ SPECIAL
Definition: setting.hh:7
@ PUSH
Definition: setting.hh:6
@ RULE
Definition: setting.hh:6
@ SHOW
Definition: setting.hh:6
@ POP
Definition: setting.hh:6
A string of characters.
Definition: t1part.c:49
Definition: inftrees.h:24
Definition: pbmfont.h:11
Definition: pbmfont.h:4
Definition: afm2pl.c:145
Definition: afm2pl.c:139
Definition: zic.c:306
#define c2
Definition: t1io.c:53
#define c1
Definition: t1io.c:52
ch
Definition: t4ht.c:1443
ch2
Definition: tex4ht.c:3229
m
Definition: tex4ht.c:3990
@ after
Definition: texnodes.h:374
int mapping
Definition: ttf2pfb.c:116
struct _lig lig
Definition: ttf2tfm.h:48