~ubuntu-branches/ubuntu/lucid/lcdf-typetools/lucid

« back to all changes in this revision

Viewing changes to otftotfm/metrics.cc

  • Committer: Bazaar Package Importer
  • Author(s): C.M. Connelly
  • Date: 2010-01-20 01:19:30 UTC
  • mfrom: (1.2.11 upstream) (3.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100120011930-l2gn28dmguk4zgb5
Tags: 2.82-1
* New upstream release.
* otftotfm: Fixes em and ex measurements with TrueType fonts (from 2.81).
* otftotfm: Fixes handling of multiply encoded glyphs (glyphs in more
  than one slot).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* metrics.{cc,hh} -- an encoding during and after OpenType features
2
2
 *
3
 
 * Copyright (c) 2003-2008 Eddie Kohler
 
3
 * Copyright (c) 2003-2010 Eddie Kohler
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or modify it
6
6
 * under the terms of the GNU General Public License as published by the Free
121
121
}
122
122
 
123
123
Metrics::Code
124
 
Metrics::hard_encoding(Glyph g) const
 
124
Metrics::hard_encoding(Glyph g, Code after) const
125
125
{
126
126
    if (g < 0)
127
127
        return -1;
128
128
    int answer = -1, n = 0;
129
 
    for (int i = _encoding.size() - 1; i >= 0; i--)
 
129
    for (int i = _encoding.size() - 1; i >= after; i--)
130
130
        if (_encoding[i].glyph == g)
131
131
            answer = i, n++;
132
 
    if (n < 2) {
 
132
    if (n < 2 && after == 0) {
133
133
        if (g >= _emap.size())
134
134
            _emap.resize(g + 1, -2);
135
135
        _emap[g] = answer;
141
141
Metrics::force_encoding(Glyph g, int lookup_source)
142
142
{
143
143
    assert(g >= 0);
144
 
    int e = encoding(g);
 
144
    int e = encoding(g, 0);
145
145
    if (e >= 0)
146
146
        return e;
147
147
    else {
469
469
/*****************************************************************************/
470
470
/* changed_context structure                                                 */
471
471
 
472
 
namespace {
473
 
class ChangedContext { public:
 
472
class Metrics::ChangedContext { public:
474
473
    ChangedContext(int ncodes);
475
474
    ~ChangedContext();
476
475
    typedef Metrics::Code Code;
491
490
    inline void ensure_all(Code) const;
492
491
};
493
492
 
494
 
ChangedContext::ChangedContext(int ncodes)
 
493
Metrics::ChangedContext::ChangedContext(int ncodes)
495
494
    : _v(ncodes, 0), _initial_ncodes(ncodes), _all_sentinel(((ncodes - 1) >> 5) + 1, 0xFFFFFFFFU)
496
495
{
497
496
}
498
497
 
499
 
ChangedContext::~ChangedContext()
 
498
Metrics::ChangedContext::~ChangedContext()
500
499
{
501
500
    for (Vector<uint32_t> **v = _v.begin(); v != _v.end(); v++)
502
501
        if (*v != &_all_sentinel)
504
503
}
505
504
 
506
505
inline void
507
 
ChangedContext::ensure_all(Code c) const
 
506
Metrics::ChangedContext::ensure_all(Code c) const
508
507
{
509
508
    if (c >= 0 && (c >> 5) >= _all_sentinel.size())
510
509
        _all_sentinel.resize((c >> 5) + 1, 0xFFFFFFFFU);
511
510
}
512
511
 
513
512
inline bool
514
 
ChangedContext::bit(const Vector<uint32_t> &v, Code c)
 
513
Metrics::ChangedContext::bit(const Vector<uint32_t> &v, Code c)
515
514
{
516
515
    if (c < 0 || (c >> 5) >= v.size())
517
516
        return false;
520
519
}
521
520
 
522
521
bool
523
 
ChangedContext::allowed(Code c, bool left_context) const
 
522
Metrics::ChangedContext::allowed(Code c, bool left_context) const
524
523
{
525
524
    if (c < 0)
526
525
        return false;
531
530
}
532
531
 
533
532
bool
534
 
ChangedContext::pair_allowed(Code c1, Code c2) const
 
533
Metrics::ChangedContext::pair_allowed(Code c1, Code c2) const
535
534
{
536
535
    ensure_all(c2);
537
536
    if (c1 < 0 || c2 < 0)
543
542
}
544
543
 
545
544
bool
546
 
ChangedContext::virgin(Code c) const
 
545
Metrics::ChangedContext::virgin(Code c) const
547
546
{
548
547
    return (c >= 0 && (c >= _v.size() || _v[c] == 0));
549
548
}
550
549
 
551
550
void
552
 
ChangedContext::disallow(Code c)
 
551
Metrics::ChangedContext::disallow(Code c)
553
552
{
554
553
    assert(c >= 0);
555
554
    if (c >= _v.size())
561
560
}
562
561
 
563
562
void
564
 
ChangedContext::disallow_pair(Code c1, Code c2)
 
563
Metrics::ChangedContext::disallow_pair(Code c1, Code c2)
565
564
{
566
565
    assert(c1 >= 0 && c2 >= 0);
567
566
    if (c1 >= _v.size())
575
574
    }
576
575
}
577
576
 
578
 
}
579
 
 
580
577
 
581
578
/*****************************************************************************/
582
579
/* applying GSUB substitutions                                               */
583
580
 
584
581
void
 
582
Metrics::apply_single(Code cin, const Substitution *s, int lookup,
 
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++)
 
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);
 
620
            }
 
621
    }
 
622
 
 
623
    // no more substitutions for cin
 
624
    ctx.disallow(cin);
 
625
}
 
626
 
 
627
void
585
628
Metrics::apply_ligature(const Vector<Code> &in, const Substitution *s, int lookup)
586
629
{
587
630
    // build up the character pair
622
665
                    repoint_ligature(ch - _encoding.begin(), l, cout);
623
666
}
624
667
 
 
668
void
 
669
Metrics::apply_simple_context_ligature(const Vector<Code> &codes,
 
670
                        const Substitution *s, int lookup, ChangedContext &ctx)
 
671
{
 
672
    int nleft = s->left_nglyphs(), nin = s->in_nglyphs();
 
673
    assert(codes.size() >= 2);
 
674
 
 
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))
 
678
            return;
 
679
 
 
680
    // check if any part of the combination has already changed
 
681
    int ncheck = nleft + (nin > 2 ? 2 : nin);
 
682
    if (ncheck == codes.size())
 
683
        --ncheck;
 
684
    for (const Code *inp = codes.begin(); inp < codes.begin() + ncheck; ++inp)
 
685
        if (!ctx.pair_allowed(inp[0], inp[1]))
 
686
            return;
 
687
 
 
688
    // mark this combination as changed if appropriate
 
689
    if (codes.size() == 2 && nin == 1)
 
690
        ctx.disallow_pair(codes[0], codes[1]);
 
691
 
 
692
    // actually apply ligature
 
693
    apply_ligature(codes, s, lookup);
 
694
}
 
695
 
 
696
bool
 
697
Metrics::next_encoding(Vector<Code> &codes, const Vector<Glyph> &glyphs) const
 
698
{
 
699
    if (!codes.size()) {
 
700
        codes.assign(glyphs.size(), 0);
 
701
        for (int i = 0; i < glyphs.size(); ++i)
 
702
            if ((codes[i] = encoding(glyphs[i], 0)) < 0)
 
703
                return false;
 
704
        return true;
 
705
    } else {
 
706
        for (int i = 0; i < glyphs.size(); ++i)
 
707
            if ((codes[i] = encoding(glyphs[i], codes[i] + 1)) >= 0)
 
708
                return true;
 
709
            else
 
710
                codes[i] = encoding(glyphs[i], 0);
 
711
        return false;
 
712
    }
 
713
}
 
714
 
625
715
int
626
716
Metrics::apply(const Vector<Substitution>& sv, bool allow_single, int lookup, const GlyphFilter& glyph_filter, const Vector<PermString>& glyph_names)
627
717
{
 
718
    Vector<Glyph> glyphs;
 
719
    Vector<Code> codes;
 
720
 
628
721
    // keep track of what substitutions we have performed
629
722
    ChangedContext ctx(_encoding.size());
630
723
 
631
 
    // XXX does not handle multiply-encoded glyphs
632
 
 
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) {
638
 
            // check if encoded
639
 
            Code cin = encoding(s->in_glyph());
640
 
            if (!ctx.allowed(cin, false))
641
 
                /* not encoded before this substitution began, or completely
642
 
                   changed; ingore */
643
 
                continue;
644
 
 
645
 
            // check if substitution of this code allowed
646
 
            if (!glyph_filter.allow_substitution(s->in_glyph(), glyph_names, unicode(cin)))
647
 
                continue;
648
 
 
649
 
            // look for an allowed alternate
650
 
            Glyph out = -1;
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
655
 
                continue;
656
 
 
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;
664
 
                ctx.disallow(cin);
665
 
            } else {
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);
674
 
                    }
675
 
                ctx.disallow(cin);
676
 
            }
677
 
 
678
 
        } else if (!is_single && !s->is_multiple() && s->is_simple_context()) {
679
 
            // find a list of 'in' codes
680
 
            Vector<Code> in;
681
 
            s->all_in_glyphs(in);
682
 
            int nleft = s->left_nglyphs(), nin = s->in_nglyphs();
683
 
            assert(in.size() >= 2);
684
 
            bool ok = true;
685
 
            for (Glyph *inp = in.begin(); inp < in.end(); inp++) {
686
 
                *inp = encoding(*inp);
687
 
                if (!ctx.allowed(*inp, inp - in.begin() < nleft))
688
 
                    ok = false;
689
 
            }
690
 
 
691
 
            // check if any part of the combination has already changed
692
 
            int ncheck = nleft + (nin > 2 ? 2 : nin);
693
 
            if (ncheck == in.size())
694
 
                ncheck--;
695
 
            for (Code *inp = in.begin(); inp < in.begin() + ncheck; inp++)
696
 
                if (!ctx.pair_allowed(inp[0], inp[1]))
697
 
                    ok = false;
698
 
 
699
 
            // if not ok, continue
700
 
            if (!ok)
701
 
                continue;
702
 
 
703
 
            // mark this combination as changed if appropriate
704
 
            if (in.size() == 2 && nin == 1)
705
 
                ctx.disallow_pair(in[0], in[1]);
706
 
 
707
 
            // actually apply ligature
708
 
            apply_ligature(in, s, lookup);
709
 
 
 
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();
 
730
 
 
731
        if (is_apply_single || is_apply_simple_context_ligature) {
 
732
            s->all_in_glyphs(glyphs);
 
733
            for (codes.clear(); next_encoding(codes, glyphs); ) {
 
734
                if (is_apply_single)
 
735
                    apply_single(codes[0], s, lookup, ctx, glyph_filter, glyph_names);
 
736
                else
 
737
                    apply_simple_context_ligature(codes, s, lookup, ctx);
 
738
            }
710
739
        } else
711
740
            failures++;
712
741
    }
715
744
}
716
745
 
717
746
void
 
747
Metrics::apply_alternates_single(Code cin, const Substitution *s, int lookup,
 
748
                const GlyphFilter &glyph_filter,
 
749
                const Vector<PermString> &glyph_names)
 
750
{
 
751
    for (const Kern *as = _altselectors.begin(); as != _altselectors.end(); as++)
 
752
        if (as->kern == 0) {
 
753
            Code last = cin;
 
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);
 
759
                    last = out;
 
760
                }
 
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);
 
764
        }
 
765
}
 
766
 
 
767
void
 
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)
 
772
{
 
773
    // check whether the output character is allowed
 
774
    if (!glyph_filter.allow_alternate(s->out_glyph(), glyph_names, 0))
 
775
        return;
 
776
 
 
777
    // find alternate selector and apply ligature if appropriate
 
778
    for (const Kern *as = _altselectors.begin(); as != _altselectors.end(); as++)
 
779
        if (as->kern == 0) {
 
780
            Vector<Code> lig(codes);
 
781
            lig.insert(lig.begin() + 1, as->in2);
 
782
            apply_ligature(lig, s, lookup);
 
783
        }
 
784
}
 
785
 
 
786
void
718
787
Metrics::apply_alternates(const Vector<Substitution>& sv, int lookup, const GlyphFilter& glyph_filter, const Vector<PermString>& glyph_names)
719
788
{
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());
723
 
            if (e < 0)
724
 
                continue;
725
 
            for (const Kern *as = _altselectors.begin(); as != _altselectors.end(); as++)
726
 
                if (as->kern == 0) {
727
 
                    Code last = e;
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);
732
 
                            last = out;
733
 
                        }
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);
737
 
                }
738
 
        } else if (s->is_ligature()) {
739
 
            // check whether the output character is allowed
740
 
            bool ok = true;
741
 
            if (!glyph_filter.allow_alternate(s->out_glyph(), glyph_names, 0))
742
 
                ok = false;
743
 
 
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)
747
 
                ok = false;
748
 
            for (int i = 1; ok && i < s->in_nglyphs(); i++)
749
 
                if ((in[i+1] = encoding(s->in_glyph(i))) < 0)
750
 
                    ok = false;
751
 
 
752
 
            if (!ok)
753
 
                continue;
754
 
 
755
 
            // find alternate selector and apply ligature if appropriate
756
 
            for (const Kern *as = _altselectors.begin(); as != _altselectors.end(); as++)
757
 
                if (as->kern == 0) {
758
 
                    in[1] = as->in2;
759
 
                    apply_ligature(in, s, lookup);
760
 
                }
 
789
    Vector<Glyph> glyphs;
 
790
    Vector<Code> codes;
 
791
 
 
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); ) {
 
797
                if (is_single)
 
798
                    apply_alternates_single(codes[0], s, lookup, glyph_filter, glyph_names);
 
799
                else
 
800
                    apply_alternates_ligature(codes, s, lookup, glyph_filter, glyph_names);
 
801
            }
761
802
        }
 
803
    }
762
804
}
763
805
 
764
806
 
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);
789
 
 
790
 
    // XXX does not handle multiply-encoded glyphs
 
831
    Vector<Glyph> glyphs;
 
832
    Vector<Code> codes;
791
833
 
792
834
    // loop over substitutions
793
835
    int success = 0;
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);
801
 
            success++;
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;
808
 
            }
 
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); )
 
841
                if (is_single) {
 
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;
 
846
                    }
 
847
                } else {
 
848
                    if (!assign_bitvec(pair_changed[codes[0]], codes[1], _encoding.size()))
 
849
                        add_kern(codes[0], codes[1], p->left().adx);
 
850
                }
809
851
            success++;
810
852
        }
 
853
    }
811
854
 
812
855
    delete[] single_changed;
813
856
    for (int i = 0; i < pair_changed.size(); i++)