581
578
/*****************************************************************************/
582
579
/* applying GSUB substitutions */
582
Metrics::apply_single(Code cin, const Substitution *s, int lookup,
583
ChangedContext &ctx, const GlyphFilter &glyph_filter,
584
const Vector<PermString> &glyph_names)
587
if (!ctx.allowed(cin, false))
588
/* not encoded before this substitution began, or completely changed;
592
// check if substitution of this code allowed
593
if (!glyph_filter.allow_substitution(s->in_glyph(), glyph_names, unicode(cin)))
596
// look for an allowed alternate
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
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;
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++)
616
if (_encoding[right].visible() && !_encoding[right].flag(Char::BUILT) && ctx.pair_allowed(cin, right)) {
617
Code pair = pair_code(cout, right, lookup);
618
_encoding[cout].flags &= ~Char::INTERMEDIATE;
619
add_ligature(cin, right, pair);
623
// no more substitutions for cin
585
628
Metrics::apply_ligature(const Vector<Code> &in, const Substitution *s, int lookup)
587
630
// build up the character pair
622
665
repoint_ligature(ch - _encoding.begin(), l, cout);
669
Metrics::apply_simple_context_ligature(const Vector<Code> &codes,
670
const Substitution *s, int lookup, ChangedContext &ctx)
672
int nleft = s->left_nglyphs(), nin = s->in_nglyphs();
673
assert(codes.size() >= 2);
675
// check if context allows substitutions
676
for (const Code *inp = codes.begin(); inp < codes.end(); ++inp)
677
if (!ctx.allowed(*inp, inp - codes.begin() < nleft))
680
// check if any part of the combination has already changed
681
int ncheck = nleft + (nin > 2 ? 2 : nin);
682
if (ncheck == codes.size())
684
for (const Code *inp = codes.begin(); inp < codes.begin() + ncheck; ++inp)
685
if (!ctx.pair_allowed(inp[0], inp[1]))
688
// mark this combination as changed if appropriate
689
if (codes.size() == 2 && nin == 1)
690
ctx.disallow_pair(codes[0], codes[1]);
692
// actually apply ligature
693
apply_ligature(codes, s, lookup);
697
Metrics::next_encoding(Vector<Code> &codes, const Vector<Glyph> &glyphs) const
700
codes.assign(glyphs.size(), 0);
701
for (int i = 0; i < glyphs.size(); ++i)
702
if ((codes[i] = encoding(glyphs[i], 0)) < 0)
706
for (int i = 0; i < glyphs.size(); ++i)
707
if ((codes[i] = encoding(glyphs[i], codes[i] + 1)) >= 0)
710
codes[i] = encoding(glyphs[i], 0);
626
716
Metrics::apply(const Vector<Substitution>& sv, bool allow_single, int lookup, const GlyphFilter& glyph_filter, const Vector<PermString>& glyph_names)
718
Vector<Glyph> glyphs;
628
721
// keep track of what substitutions we have performed
629
722
ChangedContext ctx(_encoding.size());
631
// XXX does not handle multiply-encoded glyphs
633
724
// loop over substitutions
634
725
int failures = 0;
635
726
for (const Substitution *s = sv.begin(); s != sv.end(); s++) {
636
727
bool is_single = s->is_single() || s->is_alternate();
637
if (is_single && allow_single) {
639
Code cin = encoding(s->in_glyph());
640
if (!ctx.allowed(cin, false))
641
/* not encoded before this substitution began, or completely
645
// check if substitution of this code allowed
646
if (!glyph_filter.allow_substitution(s->in_glyph(), glyph_names, unicode(cin)))
649
// look for an allowed alternate
651
for (int i = 0; out < 0 && i < s->out_nglyphs(); i++)
652
if (glyph_filter.allow_alternate(s->out_glyph(i), glyph_names, unicode(cin)))
653
out = s->out_glyph(i);
654
if (out < 0) // no allowed alternate
657
// apply substitution
658
if (ctx.virgin(cin)) {
659
// no one has changed this glyph yet, change it unilaterally
660
assign_emap(s->in_glyph(), -2);
661
assign_emap(out, cin);
662
assert(!_encoding[cin].virtual_char);
663
_encoding[cin].glyph = out;
666
// some contextual substitutions have changed this glyph, add
667
// contextual substitutions for the remaining possibilities
668
Code cout = force_encoding(out, lookup);
669
for (Code right = 0; right < _encoding.size(); right++)
670
if (_encoding[right].visible() && !_encoding[right].flag(Char::BUILT) && ctx.pair_allowed(cin, right)) {
671
Code pair = pair_code(cout, right, lookup);
672
_encoding[cout].flags &= ~Char::INTERMEDIATE;
673
add_ligature(cin, right, pair);
678
} else if (!is_single && !s->is_multiple() && s->is_simple_context()) {
679
// find a list of 'in' codes
681
s->all_in_glyphs(in);
682
int nleft = s->left_nglyphs(), nin = s->in_nglyphs();
683
assert(in.size() >= 2);
685
for (Glyph *inp = in.begin(); inp < in.end(); inp++) {
686
*inp = encoding(*inp);
687
if (!ctx.allowed(*inp, inp - in.begin() < nleft))
691
// check if any part of the combination has already changed
692
int ncheck = nleft + (nin > 2 ? 2 : nin);
693
if (ncheck == in.size())
695
for (Code *inp = in.begin(); inp < in.begin() + ncheck; inp++)
696
if (!ctx.pair_allowed(inp[0], inp[1]))
699
// if not ok, continue
703
// mark this combination as changed if appropriate
704
if (in.size() == 2 && nin == 1)
705
ctx.disallow_pair(in[0], in[1]);
707
// actually apply ligature
708
apply_ligature(in, s, lookup);
728
bool is_apply_single = is_single && allow_single;
729
bool is_apply_simple_context_ligature = !is_single && !s->is_multiple() && s->is_simple_context();
731
if (is_apply_single || is_apply_simple_context_ligature) {
732
s->all_in_glyphs(glyphs);
733
for (codes.clear(); next_encoding(codes, glyphs); ) {
735
apply_single(codes[0], s, lookup, ctx, glyph_filter, glyph_names);
737
apply_simple_context_ligature(codes, s, lookup, ctx);
747
Metrics::apply_alternates_single(Code cin, const Substitution *s, int lookup,
748
const GlyphFilter &glyph_filter,
749
const Vector<PermString> &glyph_names)
751
for (const Kern *as = _altselectors.begin(); as != _altselectors.end(); as++)
754
uint32_t u = unicode(cin);
755
for (int i = 0; i < s->out_nglyphs(); i++)
756
if (glyph_filter.allow_alternate(s->out_glyph(i), glyph_names, u)) {
757
Code out = force_encoding(s->out_glyph(i), lookup);
758
add_ligature(last, as->in2, out);
761
} else if (as->kern <= s->out_nglyphs()) {
762
Code out = force_encoding(s->out_glyph(as->kern - 1), lookup);
763
add_ligature(cin, as->in2, out);
768
Metrics::apply_alternates_ligature(const Vector<Code> &codes,
769
const Substitution *s, int lookup,
770
const GlyphFilter &glyph_filter,
771
const Vector<PermString> &glyph_names)
773
// check whether the output character is allowed
774
if (!glyph_filter.allow_alternate(s->out_glyph(), glyph_names, 0))
777
// find alternate selector and apply ligature if appropriate
778
for (const Kern *as = _altselectors.begin(); as != _altselectors.end(); as++)
780
Vector<Code> lig(codes);
781
lig.insert(lig.begin() + 1, as->in2);
782
apply_ligature(lig, s, lookup);
718
787
Metrics::apply_alternates(const Vector<Substitution>& sv, int lookup, const GlyphFilter& glyph_filter, const Vector<PermString>& glyph_names)
720
for (const Substitution *s = sv.begin(); s != sv.end(); s++)
721
if (s->is_single() || s->is_alternate()) {
722
Code e = encoding(s->in_glyph());
725
for (const Kern *as = _altselectors.begin(); as != _altselectors.end(); as++)
728
for (int i = 0; i < s->out_nglyphs(); i++)
729
if (glyph_filter.allow_alternate(s->out_glyph(i), glyph_names, unicode(e))) {
730
Code out = force_encoding(s->out_glyph(i), lookup);
731
add_ligature(last, as->in2, out);
734
} else if (as->kern <= s->out_nglyphs()) {
735
Code out = force_encoding(s->out_glyph(as->kern - 1), lookup);
736
add_ligature(e, as->in2, out);
738
} else if (s->is_ligature()) {
739
// check whether the output character is allowed
741
if (!glyph_filter.allow_alternate(s->out_glyph(), glyph_names, 0))
744
// check whether the input characters are encoded
745
Vector<Code> in(s->in_nglyphs() + 1, 0);
746
if (ok && (in[0] = encoding(s->in_glyph(0))) < 0)
748
for (int i = 1; ok && i < s->in_nglyphs(); i++)
749
if ((in[i+1] = encoding(s->in_glyph(i))) < 0)
755
// find alternate selector and apply ligature if appropriate
756
for (const Kern *as = _altselectors.begin(); as != _altselectors.end(); as++)
759
apply_ligature(in, s, lookup);
789
Vector<Glyph> glyphs;
792
for (const Substitution *s = sv.begin(); s != sv.end(); s++) {
793
bool is_single = s->is_single() || s->is_alternate();
794
if (is_single || s->is_ligature()) {
795
s->all_in_glyphs(glyphs);
796
for (codes.clear(); next_encoding(codes, glyphs); ) {
798
apply_alternates_single(codes[0], s, lookup, glyph_filter, glyph_names);
800
apply_alternates_ligature(codes, s, lookup, glyph_filter, glyph_names);
786
828
// keep track of what substitutions we have performed
787
829
int *single_changed = 0;
788
830
Vector<int *> pair_changed(_encoding.size(), 0);
790
// XXX does not handle multiply-encoded glyphs
831
Vector<Glyph> glyphs;
792
834
// loop over substitutions
794
for (const Positioning *p = pv.begin(); p != pv.end(); p++)
795
if (p->is_pairkern()) {
796
int code1 = encoding(p->left_glyph());
797
int code2 = encoding(p->right_glyph());
798
if (code1 >= 0 && code2 >= 0
799
&& !assign_bitvec(pair_changed[code1], code2, _encoding.size()))
800
add_kern(code1, code2, p->left().adx);
802
} else if (p->is_single()) {
803
int code = encoding(p->left_glyph());
804
if (code >= 0 && !assign_bitvec(single_changed, code, _encoding.size())) {
805
_encoding[code].pdx += p->left().pdx;
806
_encoding[code].pdy += p->left().pdy;
807
_encoding[code].adx += p->left().adx;
836
for (const Positioning *p = pv.begin(); p != pv.end(); p++) {
837
bool is_single = p->is_single();
838
if (is_single || p->is_pairkern()) {
839
p->all_in_glyphs(glyphs);
840
for (codes.clear(); next_encoding(codes, glyphs); )
842
if (!assign_bitvec(single_changed, codes[0], _encoding.size())) {
843
_encoding[codes[0]].pdx += p->left().pdx;
844
_encoding[codes[0]].pdy += p->left().pdy;
845
_encoding[codes[0]].adx += p->left().adx;
848
if (!assign_bitvec(pair_changed[codes[0]], codes[1], _encoding.size()))
849
add_kern(codes[0], codes[1], p->left().adx);
812
855
delete[] single_changed;
813
856
for (int i = 0; i < pair_changed.size(); i++)