From: Jan Nieuwenhuizen Date: Mon, 25 Jan 1999 16:38:52 +0000 (+0100) Subject: patch::: 1.1.24.jcn1: jcn1 X-Git-Tag: release/1.1.25~3 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=8628349cbe6f17176c6124731c9f2fb8d833ab60;p=lilypond.git patch::: 1.1.24.jcn1: jcn1 pl 24.jcn1 - bf: rest collisions - separate tfm-reader - bf: :|: should not have thin lines --- diff --git a/NEWS b/NEWS index 9234df1a8e..3063077d1c 100644 --- 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 30d5c972c8..b7ed39218c 100644 --- 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 56d25e8daf..3311ca71d7 100644 --- 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. diff --git a/input/test/collisions.ly b/input/test/collisions.ly index f057211c7f..79614c6614 100644 --- a/input/test/collisions.ly +++ b/input/test/collisions.ly @@ -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 } diff --git a/lily/include/lily-proto.hh b/lily/include/lily-proto.hh index a066878859..fb46f112a2 100644 --- a/lily/include/lily-proto.hh +++ b/lily/include/lily-proto.hh @@ -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 index 0000000000..b1c15a3b95 --- /dev/null +++ b/lily/include/tfm-reader.hh @@ -0,0 +1,42 @@ +/* + tfm-reader.hh -- declare Tex_font_metric_reader + + source file of the GNU LilyPond music typesetter + + (c) 1999 Jan Nieuwenhuizen + + + 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* ligature_arr_p, Array * kern_arr_p); + + Tex_font_metric tfm_; + Binary_source_file input_; +}; + + +#endif /* TFM_READER_HH */ + diff --git a/lily/include/tfm.hh b/lily/include/tfm.hh index 182fded427..a1db42f694 100644 --- a/lily/include/tfm.hh +++ b/lily/include/tfm.hh @@ -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 char_metrics_; Array 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* ligature_arr_p, Array * kern_arr_p); }; diff --git a/lily/lookup.cc b/lily/lookup.cc index 757cf25535..585aacaa3e 100644 --- a/lily/lookup.cc +++ b/lily/lookup.cc @@ -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 == "||") diff --git a/lily/rest-collision.cc b/lily/rest-collision.cc index 35a41c6f9d..009c7c1e50 100644 --- a/lily/rest-collision.cc +++ b/lily/rest-collision.cc @@ -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 index 0000000000..a4ddd108e9 --- /dev/null +++ b/lily/tfm-reader.cc @@ -0,0 +1,325 @@ +/* + tfm-reader.cc -- implement Tex_font_metric_reader + + source file of the GNU LilyPond music typesetter + + (c) 1999 Jan Nieuwenhuizen + + + 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 * ligature_arr_p, Array * 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); +} + diff --git a/lily/tfm.cc b/lily/tfm.cc index d06707a66d..80b0f667d1 100644 --- a/lily/tfm.cc +++ b/lily/tfm.cc @@ -10,32 +10,11 @@ */ #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 * ligature_arr_p, Array * 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 (); }