Chapter 6
Extract Code of Figures

   6.1 Outline
      Ignore in Main Pass
   6.2 Preamble
   6.3 Postamble
   6.4 Body
      Rules
      Specials
      Stack
      Fonts Definition
      Fonts Activation
   6.5 Symbols from Fonts
      Activate Font
   6.6 Utilities
      Advance Page
      Set Store-Move Variables

6.1 Outline

A figure is taken to be a chunck of dvi code enclosed between ‘+’ specials. They are to be translated to, for instance, gif code.

<..vars..>+
 static BOOL  dvi_flag = FALSE, dvi_page = FALSE;
 static FILE *idv_file;
 -_-_-

<..open idv file..>
 job_name[job_name_n-1] = ’v’;
 job_name[job_name_n-2] = ’d’;
 job_name[job_name_n-3] = ’i’;
 if( (idv_file = fopen(job_name, WRITE_BIN_FLAGS)) == NULL )
    bad_in_file(job_name);
 job_name[job_name_n-3] = ’\0’;
 -_-_-

<..main’s vars..>+
 long int eof_op_n, begin_postamble;
 int dis_pages;
 -_-_-

<..extract dvi chunks..>
 job_name[job_name_n-3] = ’\0’;
 <.extract preamble.>
 page_n = 0;
 <.start first idv page.>
 while( dis_pages ){ <.extract pages.> }
 <.error notice into lg.>
 <.extract symbols.>
 <.extract postamble.>
 -_-_-

<..error notice into lg..>
 if( errCode > 0 ){
    (IGNORED) fprintf(log_file, "tex4ht.c error: %d\n", errCode);
 }
 -_-_-

<..vars..>+
 static int errCode = 0;
 -_-_-

Ignore in Main Pass

We had ‘case ’+’: {;}’ before. However, this is wrong because we want to do nothing here with regarding to directives for the gif part.

<..ivd code in main pass..>
 while( special_n-- > 0 )  (void) get_char();
 -_-_-

6.2 Preamble

<..extract preamble..>
 file_n = 14;
 (IGNORED) fseek(dvi_file, 0L, <.abs file addr.>);
 do{  ch = get_char();
      idv_char( ch );
      file_n++;
 }while( ch == <.no op.> );
 <.idv version.>
 for( i=12; i ; i-- ){  idv_char( get_char() ); }
 i = get_char();
 idv_char( (int) i );  while( i-- ) idv_copy();
 -_-_-

<..idv version..>
 ch = get_char();
 if( id_version != -1 ){ ch = id_version; }
 idv_char( ch );
 -_-_-

<..idv version replacement num..>
 {          U_CHAR *q;
    q = p + 2;
    id_version = 0;
    while( *q != ’\0’ ){
      if( id_version != -1 ){
         if( (*q < ’0’) || (*q > ’9’) ){
            id_version = -1;
            warn_i(53);
         }
         id_version =  id_version * 10 + *q - ’0’;
      }
      q++;
 }  }
 -_-_-

<..vars..>+
 static int id_version = -1;
 -_-_-

6.3 Postamble

<..extract postamble..>
 idv_char(<.retrieve loc op.>);  file_n += 2;
 idv_char( <.end page op.> );
 (IGNORED) fseek(dvi_file, begin_postamble, <.abs file addr.>);
 begin_postamble  = file_n;
 idv_char( <.begin-postamble op.> );   file_n += 5;
 idv_int( bop_addr );  (IGNORED) fseek(dvi_file, 5L, <.relative file addr.>);
 for( i = 20; i;  i-- ) idv_copy();
 -_-_-

<..extract postamble..>+
 i = (INTEGER) get_int(2) + 1;    idv_char( (int) i >> 8 );  stack depth
 idv_char( (int) i & 0xFF );  file_n += 2;
 if( !page_n ) page_n++;   idv_char( page_n >> 8 );    page number
 idv_char( (int) page_n & 0xFF );  file_n += 2;
 (IGNORED) fseek(dvi_file, 2L, <.relative file addr.>);
 -_-_-

<..extract postamble..>+
 eof_op_n -= 32;                                       fonts
 while( --eof_op_n ) idv_copy();
 idv_int(begin_postamble);                   start postamble
 (IGNORED) fseek(dvi_file, 4L, <.relative file addr.>);  file_n += 4;
 <.idv version.>
 for( i = 8 - file_n % 4;  i;  i-- ) idv_char( <.eof op.> );
 -_-_-

6.4 Body

<..extract pages..>
 if( (ch = get_char()) < 128 ) { visible_cnt = TRUE;  cond_idv_char( ch );}
 else switch( ch ){ <.chars for idv.> }
 -_-_-

<..chars for idv..>
 case 128: case 129: case 130: case 131: case 133:
 case 134: case 135: case 136: {
   visible_cnt = TRUE;  cond_string( ch, (ch - (ch>132)) % 4 +1 );
   break;
 }
 -_-_-

Why the ‘cond_string’ above?

<..chars for idv..>+
 case   <.start page op.>: {
   x_val = 0;   y_val = 0;  stack_n = 0;
   (IGNORED) fseek(dvi_file, 44L, <.relative file addr.>);  break; }
 case     <.end page op.>: { dis_pages--; }
 case           <.no op.>: { break; }
 -_-_-

<..chars for idv..>+
 case <.mv hor dist dx.1.>: {
   cond_idv_char( ch );  x_val += dx_1;  break; }
 case <.mv hor dist dx.2.>: {
   cond_idv_char( ch );  x_val += dx_2;  break; }
 case <.mv ver dist dy.1.>: {
   cond_idv_char( ch );  y_val += dy_1;  break; }
 case <.mv ver dist dy.2.>: {
   cond_idv_char( ch );  y_val += dy_2;  break; }
 -_-_-

<..chars for idv..>+
 case <.mv hor 1-byte.>: case <.mv hor 2-byte.>:
 case <.mv hor 3-byte.>: case <.mv hor 4-byte.>: {
     cond_idv_char( ch );
     x_val += cond_int( ch - <.mv hor 1-byte.> + 1 );  break; }
 case <.dx.1 store and mv hor 1-byte.>:
 case <.dx.1 store and mv hor 2-byte.>:
 case <.dx.1 store and mv hor 3-byte.>:
 case <.dx.1 store and mv hor 4-byte.>: {
     cond_idv_char( ch );
     dx_1 = (INTEGER) cond_int( ch - <.dx.1 store and mv hor 1-byte.> + 1);
     x_val += dx_1;   break;  }
 case <.dx.2 store and mv hor 1-byte.>:
 case <.dx.2 store and mv hor 2-byte.>:
 case <.dx.2 store and mv hor 3-byte.>:
 case <.dx.2 store and mv hor 4-byte.>: {
     cond_idv_char( ch );
     dx_2 = (INTEGER) cond_int( ch - <.dx.2 store and mv hor 1-byte.> + 1);
     x_val += dx_2;   break;  }
 -_-_-

<..chars for idv..>+
 case <.mv ver 1-byte.>: case <.mv ver 2-byte.>:
 case <.mv ver 3-byte.>: case <.mv ver 4-byte.>: {
     cond_idv_char( ch );
     y_val += cond_int( ch - <.mv ver 1-byte.> + 1);
     break; }
 case <.dy.1 store and mv ver 1-byte.>:
 case <.dy.1 store and mv ver 2-byte.>:
 case <.dy.1 store and mv ver 3-byte.>:
 case <.dy.1 store and mv ver 4-byte.>: {
     cond_idv_char( ch );
     dy_1 = (INTEGER) cond_int( ch - <.dy.1 store and mv ver 1-byte.> + 1);
     y_val += dy_1;   break; }
 case <.dy.2 store and mv ver 1-byte.>:
 case <.dy.2 store and mv ver 2-byte.>:
 case <.dy.2 store and mv ver 3-byte.>:
 case <.dy.2 store and mv ver 4-byte.>: {
     cond_idv_char( ch );
     dy_2 = (INTEGER) cond_int( ch - <.dy.2 store and mv ver 1-byte.> + 1);
     y_val += dy_2;   break; }
 -_-_-

Rules

<..chars for idv..>+
 case   <.insert rule + move op.>:{
   visible_cnt = TRUE; cond_string( ch,4 ); x_val += cond_int(4);
   break;
 }
 case <.insert rule + nomove op.>:{
   visible_cnt = TRUE; cond_string( ch, 8 );
   break;
 }
 -_-_-

Specials

Only ‘+’ tex4ht specials are significant here. The ones of the form ‘\special{t4ht++...}...\special{t4ht+}’ act as delimiters for segments of dvi code to be trasmitted to the dvi driver (probably dvips). The other ones of the form ‘\special{t4ht+...}’ are ignored outside such segments, and are replaced by sub-specilas ‘\special{...}’ within the segments. For instance, ‘\special{t4ht+ps:abc}’ translates to ‘\special{ps:abc}’ within these segments. That is, the latter ones are indirect transpoters for special code (why we need this transportes?).

The non-tex4ht specials are introduced into the idv code. Those that are parts of the picture environment, are included there (dvi_page=TRUE). Those that not, are included in separate pages. The latter ones might be definitions and directives for the pictures, as is the case for pstricks which sends them to dvips.

<..chars for idv..>+
 case <.special 1.>:  case <.special 2.>:
 case <.special 3.>:  case <.special 4.>: {  long int i;
                                             int special_nr;
   special_nr = ch;
   if( tex4ht_special( &ch, &i ) ){
      if( ch == ’+’ ){
         <.handle requests for dvi to gif code.> }
      else   while( i-- ) (void)  get_char();
   }else if( dvi_flag ){ <.insert non-t4ht special into picture.>
   }else { <.insert non-t4ht special on non-picture page.> }
   break;
 }
 -_-_-

<..insert non-t4ht special on non-picture page..>
 if( dvi_page || !page_n ){ dvi_page = FALSE;  <.advance idv page.>  }
 dvi_flag = TRUE;
 <.insert non-t4ht special.>
 dvi_flag = FALSE;
 -_-_-

<..insert non-t4ht special on non-picture pageNO..>
 while( i-- )  (IGNORED) get_char();
 -_-_-

Replace the last piece with a seek! (IGNORED) fseek(dvi˙file, (long)i, ‘�relative file addr‘�);

<..insert non-t4ht special into picture..>
 visible_cnt = TRUE;   <.insert non-t4ht special.>
 -_-_-

<..insert non-t4ht special..>
 {
       U_CHAR *ch;
       int j;
    ch = special_hd;
    (IGNORED) putc( (unsigned) <.special 4.>, idv_file );  file_n++;
    for(j=4; j--; ){  (IGNORED) putc( *ch, idv_file );  file_n++;  ch++; }
    while( *ch ){  (IGNORED) putc( *ch, idv_file );  file_n++;  ch++; }
    file_n += (int) i;
    while( i-- )  (IGNORED) putc( get_char(), idv_file );
 }
 -_-_-

<..handle requests for dvi to gif code..>
 if( i==0 ){ if( dvi_flag ){ dvi_flag = 0;  <.end dvi page.> } }
 else{
   if( dvi_flag ){ <.make a special for dvi driver.> }
   else switch( get_char() ){
      case ’+’: { <.out gif filename.>
                  dvi_flag = TRUE;  dvi_page = TRUE;
                  <.advance idv page.>  break; }
      case ’@’: { <.write to lg file.> break; }
       default: { while( --i ) (void)  get_char();  break; }
 } }
 -_-_-

<..write to lg file..>
 while( --i ) (void)  putc( get_char(), log_file );
 (IGNORED) putc( ’\n’, log_file );
 -_-_-

\<handle requests for dvi to gif codeNO\><<< 
if( i==0 ){ if( dvi_flag ){ dvi_flag = 0;  ‘<end dvi page‘> } } 
else{ 
  if( dvi_flag ){ ‘<make a special for dvi driver‘> } 
  else if( ’+’==get_char() ){ 
    ‘<out gif filename‘> 
    dvi_flag = 1;  ‘<advance idv page‘> } 
  else  while( --i ) (void)  get_char(); 
} 
>>> 
 

<..out gif filename..>
 {    U_CHAR str[256], *ch;
    ch = str;   while( --i )  *(ch++) =  get_char();  *ch = ’\0’;
    script(font_gif, job_name ,page_n+1, str);
 }
 -_-_-

printf("%s", str);’— tooo much info for screen, and not that significant.

\<handle requests for dvi to gif codeNO\><<< 
if( i ){ ‘<make a special for dvi driver‘> } 
else{  dvi_flag = !dvi_flag; 
       if( dvi_flag ){ ‘<advance idv page‘> } 
       else { ‘<end dvi page‘> }                  } 
>>> 

<..make a special for dvi driver..>
 cond_idv_char( special_nr );
 cond_idv_int( i, special_nr - <.special 1.> + 1 );
 while( i-- )  cond_idv_char( get_char() );
 visible_cnt = TRUE;
 -_-_-

<..advance idv page..>
 visible_cnt = FALSE;
 bop_addr = advance_idv_page( bop_addr, cur_font );
 stack_depth = 0;
 set_loc( <.mv hor 1-byte.>, x_val );
 set_loc( <.mv ver 1-byte.>, y_val );
 -_-_-

<..idv vars..>
 INTEGER bop_addr;
 -_-_-

<..header functions..>+
 static void  set_loc( ARG_II(int, long int) );
 -_-_-

<..functions..>+
 
 static void  set_loc( op, d )
           int op;
    long   int d
 
 ;{
    idv_char( op + 3 );  int_to_dvi( d, 4 ); file_n += 5;
 }
 -_-_-

Stack

<..chars for idv..>+
 case <.sv loc op.>: {
    push_stack();
    stack_depth++;
    cond_idv_char( ch );
    break; }
 case <.retrieve loc op.>: {      INTEGER cur_x, cur_y;
    stack_depth--;
    cur_x = (INTEGER) x_val;  cur_y = (INTEGER) y_val;  pop_stack();
    if( dvi_flag ){
       if( stack_depth<0 ){ warn_i_int( 24,  page_n );
                            <.push curr state.>     }
       cond_idv_char( ch );
    }
    break; }
 -_-_-

<..push curr state..>
 cond_idv_char( <.mv hor 4-byte.> );
 idv_int( x_val - cur_x - dx_1 - dx_2 );
 cond_idv_char( <.dx.1 store and mv hor 4-byte.> );
 idv_int( dx_1 );
 cond_idv_char( <.dx.2 store and mv hor 4-byte.> );
 idv_int( dx_2 );
 cond_idv_char( <.mv ver 4-byte.> );
 idv_int( y_val - cur_y - dy_1 - dy_2 );
 cond_idv_char( <.dy.1 store and mv ver 4-byte.> );
 idv_int( dy_1 );
 cond_idv_char( <.dy.2 store and mv ver 4-byte.> );
 idv_int( dy_2 );
 cond_idv_char( <.sv loc op.> );  file_n += 24;
 -_-_-

<..end dvi page..>
 if( !visible_cnt ) {                            U_CHAR  str[256];
    (IGNORED) sprintf(str, "--- empty picture --- %sidv[%d] ---\n",
                           job_name,page_n);
    (IGNORED) printf("%s", str);  (IGNORED) fprintf(log_file, "%s",str); }
 while( stack_depth-- > 0 ){
   idv_char(<.retrieve loc op.>);  file_n++; }
 -_-_-

<..idv vars..>+
 int stack_depth=0;
 -_-_-

Fonts Definition

<..chars for idv..>+
 case <.def 4 byte font.>:
 case <.def 3 byte font.>:
 case <.def 2 byte font.>:
 case <.def 1 byte font.>: {  idv_char( ch );             file_n++;
   for( i=14; i; i-- ){  ch = get_char(); idv_char( ch ); file_n++; }
   i = ch;  i += ch = get_char();  idv_char( ch );        file_n++;
   while( i-- ){ idv_copy(); }
   break;  }
 -_-_-

Fonts Activation

The following must be consisted with the usage ‘for( i=1; i<=cur_font[0]; i++ ){’.

<..chars for idv..>+
 case  <.font 1-byte.>:
 case <.font 2-bytes.>:
 case <.font 3-bytes.>:
 case     <.font int.>: {    int i;
    idv_char( ch );  file_n++;
    cur_font[0] = ch - <.font 1-byte.> + 2;
    cur_font[1] = ch;
    for( i=2; i <= cur_font[0]; i++ ){
       ch = get_char();    idv_char( ch );
       cur_font[i] = ch;   file_n++;         }
    break;  }
 -_-_-

<..chars for idv..>+
 default: {
   if( (ch < <.font 0.>) || (ch > <.font 63.>)   ){
      if( <.font defs for xdv’s idv?.> ){
         <.xdv font def for idv.>
      } else { err_i(23); }
   }
   else {  idv_char( ch );  file_n++;
           cur_font[0] = 1;    cur_font[1] = ch;   }
   break;
 }
 -_-_-

<..idv vars..>+
 char cur_font[6];
 BOOL visible_cnt=FALSE;
 -_-_-

6.5 Symbols from Fonts

<..extract symbols..>
 {                                               int   ch, i, mag;
                                                 U_CHAR  str[256];
    (IGNORED) fprintf(log_file, "%s", begin_char_gif);
    dvi_flag = TRUE;
    for( cur_fnt = font_tbl_size; cur_fnt--; ){
       <.output to lg file.>
       for( i = font_tbl[cur_fnt].char_l - font_tbl[cur_fnt].char_f + 1;
            i--; )
          if( get_bit( font_tbl[cur_fnt].gif_on, i) ){
             bop_addr = advance_idv_page( bop_addr, cur_font );
             set_loc( <.mv hor 1-byte.>, (long int) mid_page_x );
             set_loc( <.mv ver 1-byte.>, (long int) mid_page_y );
             <.get font of symbol.>
             <.insert the char code.>        }
    }
    (IGNORED) printf("Execute script ‘%slg’\n",
                     job_name);
    (IGNORED) fclose( log_file );
 }
 -_-_-

<..insert the char code..>
 if( (ch = i + font_tbl[cur_fnt].char_f) > 127 )  {
   if( ch < 256 ) cond_idv_char(133);  else  warn_i(23);   }
 cond_idv_char( ch );
 mag = (int) ((double) font_tbl[cur_fnt].scale /
              font_tbl[cur_fnt].design_sz  * 10 );
 <.insert gif symbol to lg file.>
 script(font_gif, job_name ,page_n, str);
 -_-_-

printf("%s", str);’ — too mach info

<..open log file..>
 {      U_CHAR str[256];
    (IGNORED) strcpy((char *) str, (char *) job_name);
    str[job_name_n-1] = ’\0’;
    str[job_name_n-2] = ’g’;
    str[job_name_n-3] = ’l’;
    if( (log_file = fopen(str, WRITE_TEXT_FLAGS)) == NULL )
                                            bad_in_file(str);
 }
 -_-_-

<..vars..>+
 static FILE*  log_file;
 -_-_-

<..max page dimensions..>
 mid_page_y = (INTEGER) get_unt(4) / 2;
 mid_page_x = (INTEGER) get_unt(4) / 2;
 -_-_-

<..vars..>+
 static INTEGER mid_page_y, mid_page_x;
 -_-_-

Activate Font

<..get font of symbol..>
 {           INTEGER num;
    num = font_tbl[cur_fnt].num;
    if( num <= <.number of direct fonts.> )
                                 cond_idv_char( (int) (num + <.font 0.>) );
    else if( dvi_flag ){
      if( (num < 0) || (num > 16777215L) ) idv_int(<.font int.>);
      else if( num < 256 ) { idv_char(<.font 1-byte.>); file_n++; }
      else if( num < 65536L ) int_to_dvi((long int) <.font 2-bytes.>,2);
      else                   int_to_dvi((long int) <.font 3-bytes.>,3);
      cond_idv_char( (int) num );
 }  }
 -_-_-

The above seems to be incorrect for big numbers!!!!!!!!!!!!!!

6.6 Utilities

<..header functions..>+
 static void idv_char( ARG_I(int) );
 -_-_-

<..functions..>+
 
 static void idv_char( n )         int  n
 ;{ (IGNORED) putc( n, idv_file ); }
 -_-_-

<..header functions..>+
 static void cond_idv_char( ARG_I(int) );
 -_-_-

<..functions..>+
 
 static void cond_idv_char( n )         int  n
 ;{
    if( dvi_flag ){  (IGNORED) putc( n, idv_file );  file_n++;  }
 }
 -_-_-

<..header functions..>+
 static void idv_copy( ARG_I(void) );
 -_-_-

<..functions..>+
 static void idv_copy(  MYVOID )
 {  idv_char( get_char() );  file_n++;  }
 -_-_-

<..defines..>+
 #define idv_int(val)     int_to_dvi((long int) val,4)
 -_-_-

<..header functions..>+
 static void cond_idv_int( ARG_II(long int, int) );
 -_-_-

<..functions..>+
 
 static void cond_idv_int( val, n )  long   int val;
                              int n
 ;{
   if( dvi_flag ){  int_to_dvi((long int)  val, n );   file_n += n;  }
 }
 -_-_-

<..header functions..>+
 static void  int_to_dvi( ARG_II(long int, int) );
 -_-_-

<..functions..>+
 
 static void  int_to_dvi( val, n )  long int val;
                                 int n
 
 ;{         unsigned U_CHAR ch2, ch3, ch4;
   ch4 = (unsigned char) (val & 0xFF);   val = val >> 8;
   ch3 = (unsigned char) (val & 0xFF);   val = val >> 8;
   ch2 = (unsigned char) (val & 0xFF);   val = val >> 8;
   switch( n ){
     case 4: idv_char( (int) val );
     case 3: idv_char( ch2 );
     case 2: idv_char( ch3 );
     case 1: idv_char( ch4 ); }
   if( val & 0x80 )     val -= 0x100;
 }
 -_-_-

<..header functions..>+
 static void cond_string( ARG_II(int, int) );
 -_-_-

<..functions..>+
 
 static void cond_string(ch, n)           int  ch; int n
 
 ;{  cond_idv_char( ch );
    while( n-- )  cond_idv_char( get_char() );
 }
 -_-_-

Advance Page

<..start first idv page..>
 x_val = 0;   y_val = 0;   stack_n = 0;
 idv_char( <.start page op.> );
 idv_int( page_n + 1 );  for( i=36; i--; ) idv_char( 0);
 idv_int( -1 );  bop_addr = file_n;  file_n += 45;
 idv_char(<.sv loc op.>);  file_n++;
 -_-_-

<..vars..>+
 static int page_n,  file_n;
 -_-_-

<..header functions..>+
 static INTEGER advance_idv_page( ARG_II( INTEGER,char*) );
 -_-_-

<..functions..>+
 
 static INTEGER advance_idv_page( bop_addr, cur_font )
                                             INTEGER    bop_addr;
                                             char*  cur_font
 
 ;{                                           int    i;
    if( page_n++ ){
      idv_char(<.retrieve loc op.>);  file_n++;
      idv_char(<.end page op.>);      file_n++;
      idv_char( <.start page op.> );
      idv_int( page_n );  for( i=36; i--; ) idv_char( 0);
      idv_int( bop_addr );  bop_addr = file_n;  file_n += 45;
      idv_char(<.sv loc op.>);  file_n++;
      for( i=1; i<=cur_font[0]; i++ ){
         idv_char( cur_font[i] );   file_n++;
    } }
    <.set dx-1, dx-2, dy-1, dy-2.>
    return  bop_addr;
 }
 -_-_-

What ‘cur_font[0]’ holds?

Set Store-Move Variables

Dvips requires font definitions before the following code in the first dvi page.

<..set dx-1, dx-2, dy-1, dy-2..>
 store_mv(<.dx.1 store and mv hor 4-byte.>, dx_1);
 store_mv(<.dx.2 store and mv hor 4-byte.>, dx_2);
 store_mv(<.dy.1 store and mv ver 4-byte.>, dy_1);
 store_mv(<.dy.2 store and mv ver 4-byte.>, dy_2);
 -_-_-

<..header functions..>+
 static void store_mv( ARG_II( int, INTEGER) );
 -_-_-

<..functionsNO-sep-9..>
 
 static void store_mv(op, d)  int op;  INTEGER d
 
 ;{
    cond_idv_char(op);  cond_idv_int( (INTEGER) -d);
    cond_idv_char(op);  cond_idv_int( (INTEGER)  d);
 }
 -_-_-

<..functions..>+
 
 static void store_mv(op, d)  int op;  INTEGER d
 
 ;{
  if( dvi_flag ){
    cond_idv_char(op);  idv_int( (INTEGER) -d);
    cond_idv_char(op);  idv_int( (INTEGER)  d);  file_n += 8; }
 }
 -_-_-