class Afm_file (File):
def print_f_dimen(self, f):
- f = f * 1000
+ f = f * 1000 / self.fontsize
dimstr = '%.2f' % f
afm.write ('FontName %s\n' % name)
afm.start ('FontMetrics')
afm.start ('CharMetrics')
-
+ afm.fontsize = atof(tags[2])
elif label == "group":
ly.indent()
ly.print_lit(name)
fi
font=$1
+size=`echo $font | sed "s/[^0-9]*//"`
afm=$1.afm
-fontfile=`locate $1.tfm`
+fontfile=`kpsewhich $1.tfm`
t1=/tmp/tfmtoafm1-$$
t2=/tmp/tfmtoafm2-$$
rm -f $t1 $t2 $font $afm
for i in `seq 1 127`; do printf "%d Character-%d\n" $i $i >> $t1; done
tfmtodit $fontfile $t1 $font
rm $t1
+scaling=`nawk -v OFMT='%.5f' '/designsize/ {print $2/'$size/1000} $font`
tail -127 $font | cut -f 1-2 > $t1
cat $t1 | cut -d, -f 1-2 > $t2
rm $t1
-nl -ba $t2 | sed "s/,/ /g" | sed "s/^ *//" | sed "s/$/ /" | sed "s/^[0-9]*/C &;/" | sed "s/\([0-9]\)\([0-9][0-9][0-9][0-9][0-9]\) /\1.\2 /"g | sed "s/-[0-9]*/&; B 0.00 0.00 /" > $t1
+nl -ba $t2 | nawk -F '[ \t,]+' '{print "C "$2";\t"$3";\tB 0.00 0.00 "$4/'"$scaling"'" "$5/'"$scaling"'";"}' > $t1
+
cat > $afm <<EOF
FontName cmr
StartFontMetrics
operator Real();
operator int();
bool to_bool () const;
+ Rational to_rat () const;
+ int to_i () const;
+ Real to_f () const;
/*
urg, these are bit silly; perhaps should make "Print_string" class
}
Scalar::operator Rational ()
+{
+ return to_rat ();
+}
+
+Rational
+Scalar::to_rat () const
{
int p = index_i ('/');
if (p == -1)
- return int (*this);
+ return this->to_i ();
String s2 = right_str (length_i ()-p-1);
String s1 = left_str (p);
}
Scalar::operator Real()
+{
+ return to_f ();
+}
+
+Real
+Scalar::to_f () const
{
assert (isnum_b ());
return value_f ();
}
-Scalar::operator int()
+Scalar::operator int ()
+{
+ return to_i ();
+}
+
+int
+Scalar::to_i () const
{
if (!length_i ())
return 0; // ugh
}
tab = \notes\transpose c'''\chords{
- c1 c-m c-4 c-m4 c-5+ c-5- c-m5- c-5-5+ c-6\break %c-m6\break
- % Han-Wen: try this instead, and Wierd Things (spacing etc) happen:
-% \notes {<c1 e g>} c1-m c-4 c-m4 c-5+ c-5- c-m5- c-5-5+ c-6 c-m6\break
+ c1 c-m c-4 c-m4 c-5+ c-5- c-m5- c-5.5+ c-6\break %c-m6\break
}
\score{
Cmaj7 c-7+; c-maj
C7 c-7
Csus; Csus4 c-4; c-sus
+
%}
scales = \notes \transpose c'' \chords{
%<c1 e g>
c1-m c-min c4-dim c-aug c-sus c-maj
c1-6 c4-7 c-9 c-11 c-13
- c1-7^5 c-13^5^7^9^11
+ c1-7^5 c-13^5.7.9.11
% c1-7^5 c-13^5
c1 g d a e b fis
c1 f bes es as des ges
+ % wierd, multiple -add, ^sub
+ c-7+.9-^3.5
+ % long
+ c\breve c\longa
}
keys = \notes{
\key as; s1
\key des; s1
\key ges; s1
+ \key c; s1*2
+ \key c; s1*6
}
\score{
}
\version "1.0.14";
+twovoice = \type Staff \notes <
+ \type Voice=i { \stemdown c4 d e f g2~ g4 a [c8 d e f] c2| }
+ \type Voice=ii { \stemup g4 f e g ~ g2 g2 c4 g4 g2 }
+>
+twovoicesteminvert = \type Staff \notes <
+ % the f and g on 4th beat are exceptionally ugh.
+ \type Voice=i { \stemup c4 d e f g2 g4 a | }
+ \type Voice=ii { \stemdown g4 f e g g2 g2 }
+>
-twovoice = \notes
- \type Staff <
- { \stemdown
- c4 d e f g2~ g4 a [c8 d e f] c2| }
- { \stemup
- g4 f e g ~ g2 g2 c4 g4 g2 }
+threevoice = \type Staff \notes <
+ \type Voice=i { \stemup g4 f e f g a g2 }
+ \type Voice=ii { \stemup \property Voice.hshift = 1 e2 e2 e2 e2 }
+ \type Voice=iii { \stemdown c4 d e d c d es }
+>
- >
-
-twovoicesteminvert = \notes
- \type Staff <
- {
- \stemup
-% the f and g on 4th beat are exceptionally ugh.
- c4 d e f g2 g4 a | }
- { \stemdown
- g4 f e g g2 g2 }
- >
-
-threevoice = \notes
- \type Staff <
- { \stemup
- g4 f e f g a g2 }
- { \stemup \property Voice.hshift = 1
- e2 e2 e2 e2 }
- { \stemdown
- c4 d e d c d es }
- >
-
-
-rests = \notes
- \type Staff <
- { \stemup
- | r8 r r r r r r r
- [c' b a g] [f e d c]
- }
- { \stemdown
- [c8 d e f] [g a b c']
- r r r r r r r r
- }
- >
+rests = \type Staff \notes <
+ \type Voice=i { \stemup | r8 r r r r r r r [c' b a g] [f e d c] }
+ \type Voice = ii { \stemdown [c8 d e f] [g a b c'] r r r r r r r r }
+>
-restsII = \notes {
- \type Staff <
+restsII = \type Staff \notes {
+ \type Voice=i
+ <
{ \stemup g' f' e' d' c' b a g f e d c }
- { \stemdown r r r r r r r r r r r r }
+ \type Voice = ii { \stemdown r r r r r r r r r r r r }
>
- \type Staff <
+ <
{ \stemup r r r r r r r r r r r r }
- { \stemdown c d e f g a b c' d' e' f' g' }
+ \type Voice = ii { \stemdown c d e f g a b c' d' e' f' g' }
>
r8 r4
- \type Staff < r8 r8 >
- \type Staff < r8 r8 r8 >
- \type Staff < r8 r8 r8 r8 >
- \type Staff < r r >
- \type Staff < r r r >
+ < r8 r8 >
+ < r8 r8 r8 >
+ < r8 r8 r8 r8 >
+ < r r >
+ < r r r >
\stemup
[c''8 r8 c''8 c''8]
[c8 r8 c8 c8]
}
\score{
- \notes \transpose c' { \twovoice
+ \notes \transpose c'' { \twovoice
\twovoicesteminvert
\threevoice
\rests
% UGH ! bug!
- %\restsII
+ \restsII
}
\version "1.0.14";
-\include "table13.ly";
-\include "table16.ly";
-
\score{
<
\type Staff = a \notes\relative c <
>
\paper {
linewidth = 120.0\mm;
- -2 = \symboltables { \table_thirteen }
- -1 = \symboltables { \table_sixteen }
-
}
}
#include "afm.hh"
#include "data-file.hh"
#include "string-convert.hh"
+#include <ctype.h>
Box
strip_leading_white (String c)
{
int i=0;
- while (c[i] == ' ')
+ while (isspace(c[i]))
i++;
c = c.cut_str (i, INT_MAX);
return c;
}
Adobe_font_char_metric
-read_char_metric (String s)
+read_char_metric (String s, int size)
{
Adobe_font_char_metric char_metric;
+ char_metric.size_ = size;
Array<String> a= String_convert::split_arr (s, ';');
for (int i=0; i < a.size (); i++)
{
Array<String> b = String_convert::split_arr (c, ' ');
if (b[0] == "C")
char_metric.C_ = b[1].value_i ();
- if (b[0] == "WX")
+ else if (b[0] == "WX")
char_metric.WX_ = b[1].value_f ();
- if (b[0] == "N")
+ else if (b[0] == "N")
char_metric.N_ = strip_leading_white (b[1]);
- if (b[0] == "B")
+ else if (b[0] == "B")
char_metric.B_ = parse_box (b.slice (1, b.size()));
}
return char_metric;
}
void
-Adobe_font_metric::read_char_metrics (Data_file &input)
+Adobe_font_metric::read_char_metrics (Data_file &input, int size)
{
while (!input.eof_b ())
{
String s= input.get_line ();
if (s == "EndCharMetrics")
return ;
- Adobe_font_char_metric afm_char =read_char_metric (s);
+ Adobe_font_char_metric afm_char =read_char_metric (s, size);
char_metrics_.push (afm_char);
int i = char_metrics_.size ()-1;
ascii_to_metric_idx_ [afm_char.C_] = i;
assert (!input.eof_b ());
+ int i = fn.index_i(".afm");
+ for (; i>0 && isdigit(fn[--i]); )
+ {}
+ int font_size = String_convert::dec2_i(fn.cut_str(i+1,INT_MAX));
+
Adobe_font_metric afm;
- for (int i=0; i < 256; i++)
+ for (i=0; i < 256; i++)
{
afm.ascii_to_metric_idx_.push (-1);
}
if (key == "StartCharMetrics")
{
input.get_line ();
- afm.read_char_metrics (input);
+ afm.read_char_metrics (input, font_size);
}
if (key == "EndFontMetrics")
break;
{
Box b= B_;
- b[X_AXIS] *= 1/1000.0;
- b[Y_AXIS] *= 1/1000.0;
+ b[X_AXIS] *= size_ / 1000.0;
+ b[Y_AXIS] *= size_ / 1000.0;
return b;
}
grouping_p_ = 0;
}
-/*
- should move this to rational, but may reject now
- */
-Rational
-str2rat (String str)
+void
+Auto_beam_engraver::do_process_requests ()
{
- int num;
- int den = 1;
- if (int i = str.index_i ('/') != -1)
- {
- den = str.cut_str (i + 1, str.length_i ()).value_i ();
- str = str.left_str (i);
- }
- num = str.value_i ();
- return Rational (num, den);
+ consider_end_and_begin ();
}
void
-Auto_beam_engraver::do_process_requests ()
+Auto_beam_engraver::consider_end_and_begin ()
{
Time_description const *time = get_staff_info().time_C_;
Scalar begin = get_property ("beamAutoBegin", 0);
- Moment begin_mom = str2rat (begin);
+ Moment begin_mom = begin.to_rat ();
Scalar end = get_property ("beamAutoEnd", 0);
- Moment end_mom = str2rat (end);
+ Moment end_mom = end.to_rat ();
if (mult_i_)
{
+ int type = 1 << (mult_i_ + 2);
Scalar end_mult = get_property (String ("beamAutoEnd")
- + to_str (1 << (mult_i_ + 2)), 0);
+ + to_str (type), 0);
if (end_mult.length_i ())
- end_mom = str2rat (end_mult);
- else if (end_mom / Moment (mult_i_, 1) > Moment (4))
- end_mom /= Moment (mult_i_);
+ end_mom = end_mult.to_rat ();
+ else if (Moment (type, 4) / end_mom > Moment (4))
+ end_mom /= Moment (type, 8);
}
Real f;
}
else
{
+ int m = (rhythmic_req->duration_.durlog_i_ - 2);
+ /*
+ if multiplicity would become greater,
+ reconsider ending/starting beam first.
+ */
+ if (m > mult_i_)
+ {
+ mult_i_ = m;
+ consider_end_and_begin ();
+ }
+ mult_i_ = m;
grouping_p_->add_child (start, rhythmic_req->duration ());
stem_l->flag_i_ = rhythmic_req->duration_.durlog_i_;
beam_p_->add_stem (stem_l);
Moment now = now_moment ();
last_add_mom_ = now;
extend_mom_ = extend_mom_ >? now + rhythmic_req->duration ();
- mult_i_ = mult_i_ >? (rhythmic_req->duration_.durlog_i_ - 2);
}
}
}
Real WX_;
String N_;
Box B_;
+ int size_;
Box &bbox();
String &name();
Real &width();
Adobe_font_char_metric const &find_ascii (int ascii,bool warn) const;
String str () const;
Adobe_font_metric ();
- void read_char_metrics (Data_file &input);
+ void read_char_metrics (Data_file &input, int size);
Character_metric *get_char (int, bool) const;
private:
void begin_beam ();
+ void consider_end_and_begin ();
void end_beam ();
void junk_beam ();
void typeset_beam ();
struct Super_element;
struct Translation_property;
struct Tempo_req;
-struct Tex_font_metric;
struct Tex_font_char_metric;
+struct Tex_font_metric;
+struct Tex_font_metric_reader;
struct Text_def;
struct Text_gob;
struct Text_item ;
#ifndef LYRIC_ENGRAVER_HH
#define LYRIC_ENGRAVER_HH
+
+#include "lily-proto.hh"
#include "engraver.hh"
#include "array.hh"
-#include "lily-proto.hh"
+class Lyric_engraver : public Engraver
+{
+protected:
+ virtual void do_pre_move_processing();
+ virtual bool do_try_music (Music*);
+ virtual void do_process_requests();
+
+public:
+ Lyric_engraver ();
+ VIRTUAL_COPY_CONS (Translator);
+
+private:
+ Link_array<Lyric_req> lyric_req_l_arr_;
+ Link_array<Item> text_p_arr_;
+};
#endif // LYRIC_ENGRAVER_HH
--- /dev/null
+/*
+ tfm-reader.hh -- declare Tex_font_metric_reader
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 1999 Jan Nieuwenhuizen <janneke@gnu.org>
+
+
+ revamped code from GNU Fontutils-0.6
+
+ */
+
+#ifndef TFM_READER_HH
+#define TFM_READER_HH
+
+#include "tfm.hh"
+#include "binary-source-file.hh"
+
+class Tex_font_metric_reader
+{
+public:
+ Tex_font_metric_reader (String name);
+ Tex_font_metric read_tfm ();
+
+private:
+ Real get_U32_fix_f ();
+ Real get_U32_fix_scaled_f ();
+ String get_bcpl_str ();
+ void read_header ();
+ void read_params ();
+ void read_char_metrics ();
+ Tex_font_char_metric read_char_metric (Char_code code);
+ Tex_font_char_metric read_char ();
+ void read_lig_kern_program (Array<Tfm_ligature>* ligature_arr_p, Array <Tfm_kern>* kern_arr_p);
+
+ Tex_font_metric tfm_;
+ Binary_source_file input_;
+};
+
+
+#endif /* TFM_READER_HH */
+
class Tex_font_metric : public Font_metric
{
public:
- Character_metric *get_char (int, bool) const;
-
Tex_font_metric ();
+
+ void clear (int n);
+ Character_metric *get_char (int, bool) const;
Tex_font_char_metric const &find_ascii (int ascii, bool warn=true) const;
+ void read_file (String name);
String str () const;
- /// the reader
Tfm_info info_;
Tfm_header header_;
- void clear (int n);
- void read_file (String name);
-
Array<Tex_font_char_metric> char_metrics_;
Array<int> ascii_to_metric_idx_;
-
-private:
- Real get_U32_fix_f (Binary_source_file* input);
- Real get_U32_fix_scaled_f (Binary_source_file* input);
- String get_bcpl_str (Binary_source_file* input);
- void read_header (Binary_source_file* input);
- void read_params (Binary_source_file* input);
- void read_char_metrics (Binary_source_file* input);
- Tex_font_char_metric read_char_metric (Binary_source_file* input, Char_code code);
- Tex_font_char_metric read_char (Binary_source_file* input);
- void read_lig_kern_program (Binary_source_file* input, Array<Tfm_ligature>* ligature_arr_p, Array <Tfm_kern>* kern_arr_p);
};
Jan Nieuwenhuizen <janneke@gnu.org>
*/
+#include "lyric-engraver.hh"
#include "musical-request.hh"
-#include "main.hh"
-#include "dimensions.hh"
#include "g-text-item.hh"
-#include "engraver.hh"
-#include "array.hh"
-#include "lily-proto.hh"
+#include "paper-def.hh"
+#include "lookup.hh"
-class Lyric_engraver : public Engraver
-{
-protected:
- virtual void do_pre_move_processing();
- virtual bool do_try_music (Music*);
- virtual void do_process_requests();
-
-public:
- Lyric_engraver();
- VIRTUAL_COPY_CONS(Translator);
-
-private:
- Link_array<Lyric_req> lyric_req_l_arr_;
- Link_array<Item> text_p_arr_;
-};
-
-
-ADD_THIS_TRANSLATOR(Lyric_engraver);
+ADD_THIS_TRANSLATOR (Lyric_engraver);
Lyric_engraver::Lyric_engraver()
Scalar style = get_property ("textstyle", 0);
if (style.length_i ())
item_p->style_str_ = style;
- // urg, when/how can one get the height of this thing?
- item_p->translate (Offset (0, - i * 12 PT));
+ if (i)
+ {
+ Real dy = paper ()->lookup_l (0)-> text
+ (item_p->style_str_, String ("Cg")).dim_. y ().length ();
+ dy *= 1.1;
+ item_p->translate_axis (-i * dy, Y_AXIS);
+ }
text_p_arr_.push (item_p);
announce_element (Score_element_info (item_p, request_l));
%type <notereq> steno_notepitch
%type <pitch_arr> pitch_list
%type <music> chord notemode_chord
-%type <pitch_arr> chord_additions chord_subtractions
+%type <pitch_arr> chord_additions chord_subtractions chord_notes
%type <pitch> chord_addsub chord_note chord_inversion notemode_chord_inversion
%type <midi> midi_block midi_body
%type <duration> duration_length
;
chord:
- steno_tonic_pitch duration_length chord_additions chord_subtractions chord_inversion {
+ steno_tonic_pitch notemode_duration chord_additions chord_subtractions chord_inversion {
$$ = THIS->get_chord (*$1, $3, $4, $5, *$2);
};
notemode_chord:
- steno_musical_pitch duration_length chord_additions chord_subtractions notemode_chord_inversion {
+ steno_musical_pitch notemode_duration chord_additions chord_subtractions notemode_chord_inversion {
$$ = THIS->get_chord (*$1, $3, $4, $5, *$2);
};
{
$$ = new Array<Musical_pitch>;
}
- | chord_additions '-' chord_addsub {
+ | '-' chord_notes {
+ $$ = $2;
+ }
+ ;
+
+chord_notes:
+ {
+ $$ = new Array<Musical_pitch>;
+ }
+ | chord_notes chord_addsub {
$$ = $1;
- $$->push (*$3);
+ $$->push (*$2);
}
;
}
;
-chord_subtractions:
+chord_subtractions:
{
$$ = new Array<Musical_pitch>;
- }
- | chord_subtractions '^' chord_addsub {
- $$ = $1;
- $$->push (*$3);
+ }
+ | '^' chord_notes {
+ $$ = $2;
}
;
Rest_collision::do_post_processing()
{
/*
+ [TODO]
handle rest under beam (do_post: beams are calculated now)
-
- [todo]
- i-d like to have access to the beam itself,
- iso only the (half-initialised?) stem
-
what about combination of collisions and rest under beam
*/
-
- // no rests to collide
- if (!rest_l_arr_.size())
- return;
- // can this happen?
- Stem* stem_l = rest_l_arr_[0]->stem_l_;
- if (!stem_l)
- return;
- // no beam
- if (!(stem_l->beams_i_drul_[LEFT] || stem_l->beams_i_drul_[RIGHT]))
- return;
-
- int dir_i = rest_l_arr_[0]->dir_;
- int midpos = 4;
- // ugh
- int stem_length_i = 7 - 2;
- // ugh, Stem::stem_start vs Stem::stem_end
- int pos = (int)(stem_l->stem_end_f() - midpos) - dir_i * stem_length_i;
- /*
- nogo: stem_start not set for rests?
- int pos = (stem_l->stem_begin_f() - midpos) + dir_i * 2;
-
- WHY IS THIS STILL HERE? --hwn
- */
- rest_l_arr_[0]->translate_rests (pos);
}
void
{
// int dir_i = - ncol_l_arr_[0]->dir_;
int dir_i = rest_l_arr_[0]->dir_;
- // hope it's 4: if it works->doco
- int midpos = 0;
// minimum move
int minpos = 4;
// UGH Should get dims from table!
int size_i = 6;
+ Real internote_f = paper ()->internote_f ();
int sep_i = 3 + size_i / 2;
for (int i = 0; i < ncol_l_arr_.size(); i++)
{
// how to know whether to sort?
ncol_l_arr_[i]->sort();
for (int j = 0; j < ncol_l_arr_[i]->head_l_arr_.size(); j++)
- minpos = minpos >? dir_i *
- (ncol_l_arr_[i]->head_l_arr_[j]->position_i_ -midpos) + sep_i;
+ {
+ int stem = (int)((ncol_l_arr_[i]->stem_l_->extent
+ (Y_AXIS)[dir_i]) / internote_f);
+ minpos = minpos >? (dir_i * stem + sep_i);
+ }
}
rest_l_arr_[0]->translate_rests (dir_i * minpos);
}
Atom a= p->lookup_l(0)->text (style_str_, text_str_);
a.translate_axis (-(align_dir_ + 1)* guess_width_f (a) / 2, X_AXIS);
- // urg 1/1 is too much; see input/test/vertical-text.ly
-// a.translate_axis (a.dim_.y ().length () * 9 / 10, Y_AXIS);
- // fine for one lyric, urg for lyric chord
- a.translate_axis (a.dim_.y ().length () * 2 / 5, Y_AXIS);
return a;
}
--- /dev/null
+/*
+ tfm-reader.cc -- implement Tex_font_metric_reader
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 1999 Jan Nieuwenhuizen <janneke@gnu.org>
+
+
+ some code shamelessly copied from GNU fontutils-0.6/tfm/tfm_input.c
+ */
+
+#include "tfm-reader.hh"
+#include "string-convert.hh"
+#include "debug.hh"
+#include "warn.hh"
+
+#define format_str String_convert::form_str
+#define FIX_UNITY (1 << 20)
+static const Real fix_to_real (Fix f);
+
+
+Tex_font_metric_reader::Tex_font_metric_reader (String name)
+ : input_ (name)
+{
+ tfm_.clear (TFM_SIZE);
+}
+
+Tex_font_metric
+Tex_font_metric_reader::read_tfm ()
+{
+ read_header ();
+ read_params ();
+ read_char_metrics ();
+ return tfm_;
+}
+
+
+static const Real
+fix_to_real (Fix f)
+{
+ Real r = f / FIX_UNITY + ((Real) (f % FIX_UNITY) / (Real) FIX_UNITY);
+ return r;
+}
+
+/* Most quantities are fixed-point fractions. */
+
+Real
+Tex_font_metric_reader::get_U32_fix_f ()
+{
+ return fix_to_real (input_.get_U32 ());
+}
+
+/* Dimensions are a `Fix' scaled by the design size. */
+
+Real
+Tex_font_metric_reader::get_U32_fix_scaled_f ()
+{
+ return get_U32_fix_f () * tfm_.info_.design_size;
+}
+
+String
+Tex_font_metric_reader::get_bcpl_str ()
+{
+ U8 length_u8 = input_.get_U8 ();
+ String str = input_.get_str (length_u8);
+ return str;
+}
+
+/* Here we read the information at the beginning of the file. We store
+ the result into the static variables `global_info' and
+ `tfm_header'. */
+void
+Tex_font_metric_reader::read_header ()
+{
+ U16 file_length = input_.get_U16 ();
+ (void) file_length;
+ U16 header_length = input_.get_U16 ();
+
+ tfm_.info_.first_charcode = input_.get_U16 ();
+ tfm_.info_.last_charcode = input_.get_U16 ();
+ U16 width_word_count = input_.get_U16 ();
+ U16 height_word_count = input_.get_U16 ();
+ U16 depth_word_count = input_.get_U16 ();
+ U16 italic_correction_word_count = input_.get_U16 ();
+ U16 lig_kern_word_count = input_.get_U16 ();
+ U16 kern_word_count = input_.get_U16 ();
+ (void)kern_word_count;
+ U16 extensible_word_count = input_.get_U16 ();
+ (void)extensible_word_count;
+
+ tfm_.header_.param_word_count = input_.get_U16 ();
+ tfm_.info_.parameter_count = tfm_.header_.param_word_count;
+
+ tfm_.header_.char_info_pos = (6 + header_length) * 4;
+ tfm_.header_.width_pos = tfm_.header_.char_info_pos
+ + (tfm_.info_.last_charcode
+ - tfm_.info_.first_charcode + 1) * 4;
+ tfm_.header_.height_pos = tfm_.header_.width_pos + width_word_count * 4;
+ tfm_.header_.depth_pos = tfm_.header_.height_pos + height_word_count * 4;
+ tfm_.header_.italic_correction_pos = tfm_.header_.depth_pos
+ + depth_word_count * 4;
+ tfm_.header_.lig_kern_pos = tfm_.header_.italic_correction_pos
+ + italic_correction_word_count * 4;
+ tfm_.header_.kern_pos = tfm_.header_.lig_kern_pos + lig_kern_word_count * 4;
+ /* We don't care about the extensible table. */
+
+ if (header_length < 2)
+ error (_f ("TFM header of `%s' has only %u word(s)",
+ input_.name_str ().ch_C (), header_length));
+
+ tfm_.info_.checksum = input_.get_U32 ();
+ tfm_.info_.design_size = get_U32_fix_f ();
+
+ /* Although the coding scheme might be interesting to the caller, the
+ font family and face byte probably aren't. So we don't read them. */
+ tfm_.info_.coding_scheme = header_length > 2
+ ? get_bcpl_str () : "unspecified";
+
+ DOUT << format_str ("TFM checksum = %u, design_size = %fpt, coding scheme = `%s'.\n",
+ tfm_.info_.checksum,
+ tfm_.info_.design_size,
+ tfm_.info_.coding_scheme.ch_C ());
+}
+
+/* Although TFM files are only usable by TeX if they have at least seven
+ parameters, that is not a requirement of the file format itself, so
+ we don't impose it. And they can have many more than seven, of
+ course. We do impose a limit of TFM_MAX_FONT_PARAMETERS. We assume
+ that `tfm_header' has already been filled in. */
+
+void
+Tex_font_metric_reader::read_params ()
+{
+ /* If we have no font parameters at all, we're done. */
+ if (tfm_.header_.param_word_count == 0)
+ return;
+
+ //brrr
+ /* Move to the beginning of the parameter table in the file. */
+ input_.seek_ch_C (-4 * tfm_.header_.param_word_count);
+
+ /* It's unlikely but possible that this TFM file has more fontdimens
+ than we can deal with. */
+ if (tfm_.header_.param_word_count > TFM_MAX_FONTDIMENS)
+ {
+ warning (_f ("%s: TFM file has %u parameters, which is more than the
+%u I can handle",
+ input_.name_str ().ch_C (),
+ tfm_.header_.param_word_count,
+ TFM_MAX_FONTDIMENS));
+ tfm_.header_.param_word_count = TFM_MAX_FONTDIMENS;
+ }
+
+ /* The first parameter is different than all the rest, because it
+ isn't scaled by the design size. */
+ tfm_.info_.parameters[(TFM_SLANT_PARAMETER) - 1] = get_U32_fix_f ();
+
+ for (Char_code i = 2; i <= tfm_.header_.param_word_count; i++)
+ tfm_.info_.parameters[i - 1] = get_U32_fix_scaled_f ();
+
+#ifdef PRINT
+ for (Char_code i = 1; i <= tfm_.header_.param_word_count; i++)
+ DOUT << format_str ("TFM parameter %d: %.3f", i, tfm_.info_.parameters[i - 1]);
+#endif
+}
+
+/* Read every character in the TFM file, storing the result in the
+ static `tfm_char_table'. We return a copy of that variable. */
+
+void
+Tex_font_metric_reader::read_char_metrics ()
+{
+ for (int i = tfm_.info_.first_charcode; i <= tfm_.info_.last_charcode; i++)
+ {
+ Tex_font_char_metric tfm_char = read_char_metric (i);
+ if (tfm_char.exists_b_)
+ tfm_.ascii_to_metric_idx_[tfm_char.code_] = tfm_.char_metrics_.size ();
+ tfm_.char_metrics_.push (tfm_char);
+ }
+}
+
+/* Read the character CODE. If the character doesn't exist, return
+ NULL. If it does, save the information in `tfm_char_table', as well
+ as returning it. */
+
+Tex_font_char_metric
+Tex_font_metric_reader::read_char_metric (Char_code code)
+{
+ Tex_font_char_metric tfm_char;
+
+ /* If the character is outside the declared bounds in the file, don't
+ try to read it. */
+ if (code < tfm_.info_.first_charcode || code > tfm_.info_.last_charcode)
+ return tfm_char;
+
+ //brr
+ /* Move to the appropriate place in the `char_info' array. */
+ input_.seek_ch_C (tfm_.header_.char_info_pos + (code - tfm_.info_.first_charcode) * 4);
+
+ /* Read the character. */
+ tfm_char = read_char ();
+
+ if (tfm_char.exists_b_)
+ tfm_char.code_ = code;
+
+ return tfm_char;
+}
+
+
+/* We assume we are positioned at the beginning of a `char_info' word.
+ We read that word to get the indexes into the dimension tables; then
+ we go read the tables to get the values (if the character exists). */
+
+Tex_font_char_metric
+Tex_font_metric_reader::read_char ()
+{
+ /* Read the char_info word. */
+ U8 width_index = input_.get_U8 ();
+
+ U8 packed;
+ packed = input_.get_U8 ();
+ U8 height_index = (packed & 0xf0) >> 4;
+ U8 depth_index = packed & 0x0f;
+
+ packed = input_.get_U8 ();
+ U8 italic_correction_index = (packed & 0xfc) >> 6;
+ U8 tag = packed & 0x3;
+
+ U8 remainder = input_.get_U8 ();
+
+ Tex_font_char_metric tfm_char;
+
+#define GET_CHAR_DIMEN(d) \
+ if (d##_index != 0) \
+ { \
+ input_.seek_ch_C (tfm_.header_.##d##_pos + d##_index*4); \
+ tfm_char.d##_fix_ = input_.get_U32 (); \
+ tfm_char.d##_ = fix_to_real (tfm_char.d##_fix_) \
+ * tfm_.info_.design_size; \
+ }
+
+ GET_CHAR_DIMEN (width);
+ GET_CHAR_DIMEN (height);
+ GET_CHAR_DIMEN (depth);
+ GET_CHAR_DIMEN (italic_correction);
+
+ /* The other condition for a character existing is that it be between
+ the first and last character codes given in the header. We've
+ already assumed that's true (or we couldn't be positioned at a
+ `char_info_word'). */
+ tfm_char.exists_b_ = width_index != 0;
+
+#ifdef PRINT
+ DOUT << format_str (" width = %f, height = %f, ",
+ tfm_char.width_, tfm_char.height_);
+ DOUT << format_str ("depth = %f, ic = %f.\n",
+ tfm_char.depth, tfm_char.italic_correction);
+#endif
+
+ if (tag == 1)
+ {
+ input_.seek_ch_C (tfm_.header_.lig_kern_pos + remainder * 4);
+ read_lig_kern_program (&tfm_char.ligature_arr_, &tfm_char.kern_arr_);
+ }
+
+ /* We don't handle the other tags. */
+ return tfm_char;
+}
+
+/* Read a ligature/kern program at the current position, storing the
+ result into *LIGATURE and *KERN. We don't distinguish all the kinds
+ of ligatures that Metafont can output. */
+
+#define STOP_FLAG 128
+#define KERN_FLAG 128
+
+void
+Tex_font_metric_reader::read_lig_kern_program (Array <Tfm_ligature>* ligature_arr_p, Array <Tfm_kern>* kern_arr_p)
+{
+ bool end_b;
+
+ do
+ {
+ end_b = input_.get_U8 () >= STOP_FLAG;
+
+ U8 next_char = input_.get_U8 ();
+ bool kern_step_b = input_.get_U8 () >= KERN_FLAG;
+ U8 remainder = input_.get_U8 ();
+
+#ifdef PRINT
+ DOUT << format_str (" if next = %u (%c), ", next_char, next_char);
+#endif
+
+ if (kern_step_b)
+ {
+ Tfm_kern kern_element;
+ kern_element.character = next_char;
+
+ char const* old_pos = input_.pos_ch_C ();
+ input_.seek_ch_C (tfm_.header_.kern_pos + remainder * 4);
+ kern_element.kern = get_U32_fix_scaled_f ();
+ input_.set_pos (old_pos);
+
+ kern_arr_p->push (kern_element);
+
+#ifdef PRINT
+ DOUT << format_str ("kern %f.\n", kern_element.kern);
+#endif
+ }
+ else
+ {
+ Tfm_ligature ligature_element;
+ ligature_element.character = next_char;
+ ligature_element.ligature = remainder;
+ ligature_arr_p->push (ligature_element);
+
+#ifdef PRINT
+ DOUT format_str ("ligature %d (hex %x).\n",
+ ligature_element.ligature,
+ ligature_element.ligature);
+#endif
+ }
+ } while (!end_b);
+}
+
*/
#include "tfm.hh"
-#include "binary-source-file.hh"
+#include "tfm-reader.hh"
#include "string-convert.hh"
#include "debug.hh"
#include "warn.hh"
-#define format_str String_convert::form_str
-
-#define FIX_UNITY (1 << 20)
-
-static const Real
-fix_to_real (Fix f)
-{
- Real r = f / FIX_UNITY + ((Real) (f % FIX_UNITY) / (Real) FIX_UNITY);
- return r;
-}
-
-#if 0 //not used
-static const Fix
-real_to_fix (Real r)
-{
- Fix f = (Fix) (floor (r) * FIX_UNITY + (r - floor (r)) * FIX_UNITY);
- return f;
-}
-#endif
-
-
Box
Tex_font_char_metric::dimensions () const
{
ascii_to_metric_idx_.push (-1);
}
-/* Most quantities are fixed-point fractions. */
-
-Real
-Tex_font_metric::get_U32_fix_f (Binary_source_file* input)
-{
- return fix_to_real (input->get_U32 ());
-}
-
-
-/* Dimensions are a `Fix' scaled by the design size. */
-
-Real
-Tex_font_metric::get_U32_fix_scaled_f (Binary_source_file* input)
-{
- return get_U32_fix_f (input) * info_.design_size;
-}
-
-String
-Tex_font_metric::get_bcpl_str (Binary_source_file* input)
-{
- U8 length_u8 = input->get_U8 ();
- String str = input->get_str (length_u8);
- return str;
-}
-
-/* Here we read the information at the beginning of the file. We store
- the result into the static variables `global_info' and
- `tfm_header'. */
-void
-Tex_font_metric::read_header (Binary_source_file* input)
-{
- U16 file_length = input->get_U16 ();
- (void) file_length;
- U16 header_length = input->get_U16 ();
-
- info_.first_charcode = input->get_U16 ();
- info_.last_charcode = input->get_U16 ();
- U16 width_word_count = input->get_U16 ();
- U16 height_word_count = input->get_U16 ();
- U16 depth_word_count = input->get_U16 ();
- U16 italic_correction_word_count = input->get_U16 ();
- U16 lig_kern_word_count = input->get_U16 ();
- U16 kern_word_count = input->get_U16 ();
- (void)kern_word_count;
- U16 extensible_word_count = input->get_U16 ();
- (void)extensible_word_count;
-
- header_.param_word_count = input->get_U16 ();
- info_.parameter_count = header_.param_word_count;
-
- header_.char_info_pos = (6 + header_length) * 4;
- header_.width_pos = header_.char_info_pos
- + (info_.last_charcode
- - info_.first_charcode + 1) * 4;
- header_.height_pos = header_.width_pos + width_word_count * 4;
- header_.depth_pos = header_.height_pos + height_word_count * 4;
- header_.italic_correction_pos = header_.depth_pos
- + depth_word_count * 4;
- header_.lig_kern_pos = header_.italic_correction_pos
- + italic_correction_word_count * 4;
- header_.kern_pos = header_.lig_kern_pos + lig_kern_word_count * 4;
- /* We don't care about the extensible table. */
-
- if (header_length < 2)
- error (_f ("TFM header of `%s' has only %u word(s)",
- input->name_str ().ch_C (), header_length));
-
- info_.checksum = input->get_U32 ();
- info_.design_size = get_U32_fix_f (input);
-
- /* Although the coding scheme might be interesting to the caller, the
- font family and face byte probably aren't. So we don't read them. */
- info_.coding_scheme = header_length > 2
- ? get_bcpl_str (input) : "unspecified";
-
- DOUT << format_str ("TFM checksum = %u, design_size = %fpt, coding scheme = `%s'.\n",
- info_.checksum,
- info_.design_size,
- info_.coding_scheme.ch_C ());
-}
-
void
Tex_font_metric::read_file (String name)
{
- Binary_source_file input (name);
-
- clear (TFM_SIZE);
- read_header (&input);
- read_params (&input);
- read_char_metrics (&input);
-}
-
-/* Although TFM files are only usable by TeX if they have at least seven
- parameters, that is not a requirement of the file format itself, so
- we don't impose it. And they can have many more than seven, of
- course. We do impose a limit of TFM_MAX_FONT_PARAMETERS. We assume
- that `tfm_header' has already been filled in. */
-
-void
-Tex_font_metric::read_params (Binary_source_file* input)
-{
- /* If we have no font parameters at all, we're done. */
- if (header_.param_word_count == 0)
- return;
-
- //brrr
- /* Move to the beginning of the parameter table in the file. */
- input->seek_ch_C (-4 * header_.param_word_count);
-
- /* It's unlikely but possible that this TFM file has more fontdimens
- than we can deal with. */
- if (header_.param_word_count > TFM_MAX_FONTDIMENS)
- {
- warning (_f ("%s: TFM file has %u parameters, which is more than the
-%u I can handle",
- input->name_str ().ch_C (),
- header_.param_word_count,
- TFM_MAX_FONTDIMENS));
- header_.param_word_count = TFM_MAX_FONTDIMENS;
- }
-
- /* The first parameter is different than all the rest, because it
- isn't scaled by the design size. */
- info_.parameters[(TFM_SLANT_PARAMETER) - 1] = get_U32_fix_f (input);
-
- for (Char_code i = 2; i <= header_.param_word_count; i++)
- info_.parameters[i - 1] = get_U32_fix_scaled_f (input);
-
-#ifdef PRINT
- for (Char_code i = 1; i <= header_.param_word_count; i++)
- DOUT << format_str ("TFM parameter %d: %.3f", i, info_.parameters[i - 1]);
-#endif
-}
-
-/* Read every character in the TFM file, storing the result in the
- static `tfm_char_table'. We return a copy of that variable. */
-
-void
-Tex_font_metric::read_char_metrics (Binary_source_file* input)
-{
- for (int i = info_.first_charcode; i <= info_.last_charcode; i++)
- {
- Tex_font_char_metric tfm_char = read_char_metric (input, i);
- if (tfm_char.exists_b_)
- ascii_to_metric_idx_[tfm_char.code_] = char_metrics_.size ();
- char_metrics_.push (tfm_char);
- }
-}
-
-/* Read the character CODE. If the character doesn't exist, return
- NULL. If it does, save the information in `tfm_char_table', as well
- as returning it. */
-
-Tex_font_char_metric
-Tex_font_metric::read_char_metric (Binary_source_file* input, Char_code code)
-{
- Tex_font_char_metric tfm_char;
-
- /* If the character is outside the declared bounds in the file, don't
- try to read it. */
- if (code < info_.first_charcode || code > info_.last_charcode)
- return tfm_char;
-
- //brr
- /* Move to the appropriate place in the `char_info' array. */
- input->seek_ch_C (header_.char_info_pos + (code - info_.first_charcode) * 4);
-
- /* Read the character. */
- tfm_char = read_char (input);
-
- if (tfm_char.exists_b_)
- tfm_char.code_ = code;
-
- return tfm_char;
-}
-
-
-/* We assume we are positioned at the beginning of a `char_info' word.
- We read that word to get the indexes into the dimension tables; then
- we go read the tables to get the values (if the character exists). */
-
-Tex_font_char_metric
-Tex_font_metric::read_char (Binary_source_file* input)
-{
- /* Read the char_info word. */
- U8 width_index = input->get_U8 ();
-
- U8 packed;
- packed = input->get_U8 ();
- U8 height_index = (packed & 0xf0) >> 4;
- U8 depth_index = packed & 0x0f;
-
- packed = input->get_U8 ();
- U8 italic_correction_index = (packed & 0xfc) >> 6;
- U8 tag = packed & 0x3;
-
- U8 remainder = input->get_U8 ();
-
- Tex_font_char_metric tfm_char;
-
-#define GET_CHAR_DIMEN(d) \
- if (d##_index != 0) \
- { \
- input->seek_ch_C (header_.##d##_pos + d##_index*4); \
- tfm_char.d##_fix_ = input->get_U32 (); \
- tfm_char.d##_ = fix_to_real (tfm_char.d##_fix_) \
- * info_.design_size; \
- }
-
- GET_CHAR_DIMEN (width);
- GET_CHAR_DIMEN (height);
- GET_CHAR_DIMEN (depth);
- GET_CHAR_DIMEN (italic_correction);
-
- /* The other condition for a character existing is that it be between
- the first and last character codes given in the header. We've
- already assumed that's true (or we couldn't be positioned at a
- `char_info_word'). */
- tfm_char.exists_b_ = width_index != 0;
-
-#ifdef PRINT
- DOUT << format_str (" width = %f, height = %f, ",
- tfm_char.width_, tfm_char.height_);
- DOUT << format_str ("depth = %f, ic = %f.\n",
- tfm_char.depth, tfm_char.italic_correction);
-#endif
-
- if (tag == 1)
- {
- input->seek_ch_C (header_.lig_kern_pos + remainder * 4);
- read_lig_kern_program (input, &tfm_char.ligature_arr_, &tfm_char.kern_arr_);
- }
-
- /* We don't handle the other tags. */
- return tfm_char;
-}
-
-/* Read a ligature/kern program at the current position, storing the
- result into *LIGATURE and *KERN. We don't distinguish all the kinds
- of ligatures that Metafont can output. */
-
-#define STOP_FLAG 128
-#define KERN_FLAG 128
-
-void
-Tex_font_metric::read_lig_kern_program (Binary_source_file* input, Array <Tfm_ligature>* ligature_arr_p, Array <Tfm_kern>* kern_arr_p)
-{
- bool end_b;
-
- do
- {
- end_b = input->get_U8 () >= STOP_FLAG;
-
- U8 next_char = input->get_U8 ();
- bool kern_step_b = input->get_U8 () >= KERN_FLAG;
- U8 remainder = input->get_U8 ();
-
-#ifdef PRINT
- DOUT << format_str (" if next = %u (%c), ", next_char, next_char);
-#endif
-
- if (kern_step_b)
- {
- Tfm_kern kern_element;
- kern_element.character = next_char;
-
- char const* old_pos = input->pos_ch_C ();
- input->seek_ch_C (header_.kern_pos + remainder * 4);
- kern_element.kern = get_U32_fix_scaled_f (input);
- input->set_pos (old_pos);
-
- kern_arr_p->push (kern_element);
-
-#ifdef PRINT
- DOUT << format_str ("kern %f.\n", kern_element.kern);
-#endif
- }
- else
- {
- Tfm_ligature ligature_element;
- ligature_element.character = next_char;
- ligature_element.ligature = remainder;
- ligature_arr_p->push (ligature_element);
-
-#ifdef PRINT
- DOUT format_str ("ligature %d (hex %x).\n",
- ligature_element.ligature,
- ligature_element.ligature);
-#endif
- }
- } while (!end_b);
+ Tex_font_metric_reader tfm_reader (name);
+ *this = tfm_reader.read_tfm ();
}
\header {
composer = "Domenico Scarlatti";
- title="Sonata K.3"
+ title="Sonata K.3";
opus="L.378";
movement="Presto";
copyright = "General Public License";
> >
- \paper{
- barsize=50.0;
- }
+
}