]> git.donarmstrong.com Git - lilypond.git/commitdiff
patch::: 1.1.24.jcn1: jcn1
authorJan Nieuwenhuizen <janneke@gnu.org>
Mon, 25 Jan 1999 16:38:52 +0000 (17:38 +0100)
committerJan Nieuwenhuizen <janneke@gnu.org>
Mon, 25 Jan 1999 16:38:52 +0000 (17:38 +0100)
pl 24.jcn1
- bf: rest collisions
- separate tfm-reader
- bf: :|: should not have thin lines

NEWS
TODO
VERSION
input/test/collisions.ly
lily/include/lily-proto.hh
lily/include/tfm-reader.hh [new file with mode: 0644]
lily/include/tfm.hh
lily/lookup.cc
lily/rest-collision.cc
lily/tfm-reader.cc [new file with mode: 0644]
lily/tfm.cc

diff --git a/NEWS b/NEWS
index 9234df1a8efe73f5eea390d5aa591ad1460071b8..3063077d1cde9ea605aebdddcb69d648dbfb872b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+pl 24.jcn1
+       - bf: rest collisions
+       - separate tfm-reader
+       - bf: :|: should not have thin lines
+
 pl 24, Hacking Apart Together (Jan 25)
 
 pl 23.jbr1
diff --git a/TODO b/TODO
index 30d5c972c8860aa62082e977c60a357453876ef4..b7ed39218c3e22927f3cc972690192040ca63ca5 100644 (file)
--- a/TODO
+++ b/TODO
@@ -67,15 +67,9 @@ I also found a few bugs:
 
 BUGS:
 
-       * collisions/voices \voiceone \voicetwo are broken; see 
-         input/praeludium-fuga-E.ly
-         mutopia/J.S.Bach/wtk1-fugue2.ly
-
        * fix: text on rests: rediculous dims
 
        * ly2dvi
-         - barfs on linewidth = -1.
-         - bottomnote for ly2dvi
          - deps for ly2dvi
 
        * fix midi output:
diff --git a/VERSION b/VERSION
index 56d25e8daf2bf4844732925fb785ede5de8c4eda..3311ca71d712e326c047780ccf0a6ed81aad8186 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -2,7 +2,7 @@ PACKAGE_NAME=LilyPond
 MAJOR_VERSION=1
 MINOR_VERSION=1
 PATCH_LEVEL=24
-MY_PATCH_LEVEL=
+MY_PATCH_LEVEL=jcn1
 
 # use the above to send patches: MY_PATCH_LEVEL is always empty for a
 # released version.
index f057211c7f245a13deb1746caf7cd2e645d7cee8..79614c661455c7f0278fe768db9b8f13b7fd9633 100644 (file)
@@ -7,66 +7,45 @@ Tested =       "test the Collision resolution ";
 }
 \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]
@@ -76,12 +55,12 @@ restsII = \notes {
 }
 
 \score{
-       \notes \transpose c' {  \twovoice  
+       \notes \transpose c'' {  \twovoice  
        \twovoicesteminvert 
        \threevoice  
        \rests 
        % UGH ! bug!
-       %\restsII 
+       \restsII 
        }
        
 
index a066878859c06cd4f15b2242bd229c420238004a..fb46f112a22b53232c221a7164688d9ee2a5dd66 100644 (file)
@@ -233,8 +233,9 @@ struct Symtables;
 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 ;
diff --git a/lily/include/tfm-reader.hh b/lily/include/tfm-reader.hh
new file mode 100644 (file)
index 0000000..b1c15a3
--- /dev/null
@@ -0,0 +1,42 @@
+/*   
+  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 */
+
index 182fded427da3bbd2a3d6e5b1d43fd261ca58679..a1db42f6942827d79204929f7221029210da3278 100644 (file)
@@ -144,31 +144,18 @@ struct Tex_font_char_metric : Character_metric
 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);
 };
 
 
index 757cf25535c2980c2b0b5eb137598183bc152018..585aacaa3eeb8ecc6637e91e7cc5ff7c047441ca 100644 (file)
@@ -170,10 +170,8 @@ Lookup::bar (String str, Real h) const
   else if (str == ":|:")
     {
       m.add_at_edge (X_AXIS, LEFT, thick,kern/2);
-      m.add_at_edge (X_AXIS, LEFT, thin,kern);
       m.add_at_edge (X_AXIS, LEFT, colon,kern);      
       m.add_at_edge (X_AXIS, RIGHT, thick,kern);
-      m.add_at_edge (X_AXIS, RIGHT, thin,kern);
       m.add_at_edge (X_AXIS, RIGHT, colon,kern);      
     }
   else if (str == "||")
index 35a41c6f9d00c76d2915942c8e9504983a2deecd..009c7c1e5057af34f8b49ccfd74c95dc3c1263a0 100644 (file)
@@ -31,39 +31,10 @@ void
 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
@@ -98,8 +69,6 @@ Rest_collision::do_pre_processing()
     {
       // 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;
@@ -108,14 +77,18 @@ Rest_collision::do_pre_processing()
       // 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);        
     }
diff --git a/lily/tfm-reader.cc b/lily/tfm-reader.cc
new file mode 100644 (file)
index 0000000..a4ddd10
--- /dev/null
@@ -0,0 +1,325 @@
+/*   
+  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);
+}
+
index d06707a66d5bc198d9198473afdbaf5f684b6eef..80b0f667d16d5440ea0d77b1af5631189c94669f 100644 (file)
  */
 
 #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
 {
@@ -112,296 +91,10 @@ Tex_font_metric::clear (int n)
     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 ();
 }