Back to index

texmacs  1.0.7.15
concat_post.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : concat_post.cpp
00004 * DESCRIPTION: Second pass for typesetting paragraphs
00005 *                - The real heights of brackets are determined
00006 *                - scripts are glued
00007 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00008 *******************************************************************************
00009 * This software falls under the GNU general public license version 3 or later.
00010 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00011 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00012 ******************************************************************************/
00013 
00014 #include "concater.hpp"
00015 SI italic_correction (box, box);
00016 
00017 /******************************************************************************
00018 * Miscellaneous routines
00019 ******************************************************************************/
00020 
00021 int
00022 concater_rep::prec (int i) {
00023   do i--; while ((i>=0) && (a[i]->type==OBSOLETE_ITEM));
00024   return i;
00025 }
00026 
00027 int
00028 concater_rep::succ (int i) {
00029   do i++; while ((i<N(a)) && (a[i]->type==OBSOLETE_ITEM));
00030   return i;
00031 }
00032 
00033 /******************************************************************************
00034 * Gluing scripts
00035 ******************************************************************************/
00036 
00037 void
00038 concater_rep::pre_glue () {
00039   int i;
00040   for (i=0; i<N(a)-1; i++) {
00041     line_item item1= a[i];
00042     line_item item2= a[i+1];
00043     int t1= item1->type;
00044     int t2= item2->type;
00045     if (((t1 == RSUB_ITEM) && (t2 == RSUP_ITEM)) ||
00046        ((t1 == RSUP_ITEM) && (t2 == RSUB_ITEM)) ||
00047        ((t1 == LSUB_ITEM) && (t2 == LSUP_ITEM)) ||
00048        ((t1 == LSUP_ITEM) && (t2 == LSUB_ITEM)))
00049       {
00050        bool  flag1 = (t1 == LSUB_ITEM) || (t1 == RSUB_ITEM);
00051        bool  flag2 = (t1 == LSUB_ITEM) || (t1 == LSUP_ITEM);
00052        int   type  = flag2? GLUE_LSUBS_ITEM: GLUE_RSUBS_ITEM;
00053        box   b1    = flag1? item1->b[0]: item2->b[0];
00054        box   b2    = flag1? item2->b[0]: item1->b[0];
00055        box   b     = script_box (b1->ip, b1, b2, env->fn);
00056        int   pen   = item2->penalty;
00057        space spc   = max (item1->spc, item2->spc);
00058 
00059        a[i]= line_item (type, OP_SKIP, b, pen);
00060        a[i]->spc = spc;
00061        a[i+1]= line_item (OBSOLETE_ITEM, OP_SKIP, item2->b, pen);
00062       }
00063   }
00064 }
00065 
00066 void
00067 concater_rep::glue (box b, int ref, int arg) {
00068   space spc = max (a[ref]->spc, a[arg]->spc);
00069 
00070   a[arg]  = line_item (OBSOLETE_ITEM, OP_SKIP, a[arg]->b, a[arg]->penalty);
00071   a[ref]  = line_item (arg<ref? GLUE_LEFT_ITEM: GLUE_RIGHT_ITEM,
00072                        a[ref]->op_type, b,
00073                      min (a[ref]->penalty, a[arg]->penalty));
00074   a[ref]->spc = spc;
00075 }
00076 
00077 void
00078 concater_rep::glue (box b, int ref, int arg1, int arg2) {
00079   space spc = max (a[ref]->spc, max (a[arg1]->spc, a[arg2]->spc));
00080   int   pen = min (a[ref]->penalty, min (a[arg1]->penalty, a[arg2]->penalty));
00081 
00082   space ref_spc= a[ref]->spc;
00083   a[arg1]= line_item (OBSOLETE_ITEM, OP_SKIP, a[arg1]->b, a[arg1]->penalty);
00084   a[arg2]= line_item (OBSOLETE_ITEM, OP_SKIP, a[arg2]->b, a[arg2]->penalty);
00085   a[ref]= line_item (GLUE_BOTH_ITEM, a[ref]->op_type, b, pen);
00086   a[ref]->spc = spc;
00087 }
00088 
00089 void
00090 concater_rep::handle_scripts (int start, int end) {
00091   int i;
00092   for (i=start; i<=end; ) {
00093     if ((a[i]->type == OBSOLETE_ITEM) ||
00094        (a[i]->type == LSUB_ITEM) ||
00095        (a[i]->type == LSUP_ITEM) ||
00096        (a[i]->type == GLUE_LSUBS_ITEM) ||
00097        (a[i]->type == RSUB_ITEM) ||
00098        (a[i]->type == RSUP_ITEM) ||
00099        (a[i]->type == GLUE_RSUBS_ITEM)) { i++; continue; }
00100 
00101     path sip;
00102     int l= prec (i);
00103     box lb1, lb2;
00104     if (l < start) l= -1;
00105     else switch (a[l]->type) {
00106     case LSUB_ITEM:
00107       lb1= a[l]->b[0];
00108       sip= lb1->ip;
00109       break;
00110     case LSUP_ITEM:
00111       lb2= a[l]->b[0];
00112       sip= lb2->ip;
00113       break;
00114     case GLUE_LSUBS_ITEM:
00115       lb1= a[l]->b[0];
00116       lb2= a[l]->b[1];
00117       sip= lb2->ip;
00118       break;
00119     default:
00120       l = -1;
00121     }
00122 
00123     int r= succ (i);
00124     box rb1, rb2;
00125     if (r > end) r= N(a);
00126     else switch (a[r]->type) {
00127     case RSUB_ITEM:
00128       rb1= a[r]->b[0];
00129       sip= rb1->ip;
00130       break;
00131     case RSUP_ITEM:
00132       rb2= a[r]->b[0];
00133       sip= rb2->ip;
00134       break;
00135     case GLUE_RSUBS_ITEM:
00136       rb1= a[r]->b[0];
00137       rb2= a[r]->b[1];
00138       sip= rb2->ip;
00139       break;
00140     default:
00141       r = N(a);
00142     }
00143 
00144     box b;
00145     if ((l==-1) && (r==N(a))) { i++; continue; }
00146     if ((l!=-1) && (r==N(a))) {
00147       b= left_script_box (sip, a[i]->b, lb1, lb2, env->fn, env->vert_pos);
00148       glue (b, i, l);
00149     }
00150     if ((l==-1) && (r!=N(a))) {
00151       if (a[i]->limits)
00152        b= limit_box (sip, a[i]->b, rb1, rb2, env->fn, true);
00153       else
00154        b= right_script_box (sip, a[i]->b, rb1, rb2, env->fn, env->vert_pos);
00155       glue (b, i, r);
00156     }
00157     if ((l!=-1) && (r!=N(a))) {
00158       b= side_box (sip, a[i]->b, lb1, lb2, rb1, rb2, env->fn, env->vert_pos);
00159       glue (b, i, l, r);
00160     }
00161   }
00162 }
00163 
00164 void
00165 concater_rep::clean_and_correct () {
00166   array<line_item> new_a;
00167   int i, prev=-1;
00168   for (i=0; i<N(a); i++)
00169     if (a[i]->type!=OBSOLETE_ITEM) {
00170       if (a[i]->b->w () != 0) {
00171        if (prev != -1)
00172          a[prev]->spc += space (::italic_correction (a[prev]->b, a[i]->b));
00173        prev= i;
00174       }
00175       new_a << a[i];
00176     }
00177   a= new_a;
00178 }
00179 
00180 /******************************************************************************
00181 * Resize brackets
00182 ******************************************************************************/
00183 
00184 void
00185 concater_rep::handle_matching (int start, int end) {
00186   //cout << "matching " << start << " -- " << end << "\n";
00187   //cout << a << "\n\n";
00188   int i;
00189   SI y1= min (a[start]->b->y1, a[end]->b->y2);
00190   SI y2= max (a[start]->b->y1, a[end]->b->y2);
00191   a[start]->penalty++;
00192   a[end]->penalty++;
00193   // cout << "Start: " << (y2-y1) << "\n";
00194   for (i=start+1; i<end; i++) {
00195     if (a[i]->type == OBSOLETE_ITEM) continue;
00196     // cout << "  " << a[i] << ": " << (a[i]->b->y2- a[i]->b->y1) << "\n";
00197     // y1= min (y1, a[i]->b->sub_base());
00198     // y2= max (y2, a[i]->b->sup_base());
00199     y1= min (y1, a[i]->b->y1);
00200     y2= max (y2, a[i]->b->y2);
00201     a[i]->penalty++;
00202   }
00203   for (i=start; i<=end; i++) {
00204     int tp= a[i]->type;
00205     if (tp == LEFT_BRACKET_ITEM ||
00206        tp == MIDDLE_BRACKET_ITEM ||
00207        tp == RIGHT_BRACKET_ITEM)
00208       {
00209        // make symmetric and prevent from too large delimiters if possible
00210        font fn = a[i]->b->get_leaf_font ();
00211        SI Y1   = y1 + (fn->sep >> 1);
00212        SI Y2   = y2 - (fn->sep >> 1);
00213        SI tol  = fn->sep << 1;
00214        SI mid  = (a[i]->b->y1 + a[i]->b->y2) >> 1;
00215        SI drift= ((Y1 + Y2) >> 1) - mid; // fn->yfrac;
00216        if (drift < 0) Y2 += min (-drift, tol) << 1;
00217        else Y1 -= min (drift, tol) << 1;
00218 
00219         // further adjustments when the enclosed expression is not very heigh
00220         SI h= y2 - y1 - fn->sep;
00221         SI d= 5 * fn->yx - h;
00222         if (d > 0) { Y1 += d/12; Y2 -= d/12; }
00223 
00224         // replace item by large or small delimiter
00225         string ls= a[i]->b->get_leaf_string ();
00226         color lc= a[i]->b->get_leaf_color ();
00227         font lf= a[i]->b->get_leaf_font ();
00228         if (Y1 < fn->y1 || Y2 > fn->y2)
00229           a[i]->b= delimiter_box (a[i]->b->ip, ls, fn, lc, Y1, Y2);
00230         else {
00231           string s= "<nobracket>";
00232           int j;
00233           for (j=0; j<N(ls); j++)
00234             if (ls[j] == '-') break;
00235           if (j<N(ls) && ls[N(ls)-1] == '>') s= ls (j+1, N(ls)-1);
00236           if (N(s) > 1 && s[0] != '<') s= "<" * s * ">";
00237           else if (N(s) == 0 || s == ".") s= "<nobracket>";
00238           a[i]->b= text_box (a[i]->b->ip, 0, s, lf, lc);
00239           tp= STD_ITEM;
00240         }
00241         a[i]->type= STD_ITEM;
00242       }
00243     if (tp == LEFT_BRACKET_ITEM)
00244       for (int j= i-1; j>=0; j--) {
00245        if (a[j]->type == MARKER_ITEM) {
00246          SI Y1= a[i]->b->y1;
00247          SI Y2= a[i]->b->y2;
00248          a[j]->b   = marker_box (a[j]->b->find_lip (), 0, Y1, 0, Y2, a[j]->b);
00249          a[j]->type= STD_ITEM;
00250        }
00251        else if (a[j]->type != CONTROL_ITEM) break;
00252       }
00253     if (tp == RIGHT_BRACKET_ITEM)
00254       for (int j= i+1; j<N(a); j++) {
00255        if (a[j]->type == MARKER_ITEM) {
00256          SI Y1= a[i]->b->y1;
00257          SI Y2= a[i]->b->y2;
00258          a[j]->b   = marker_box (a[j]->b->find_lip (), 0, Y1, 0, Y2, a[j]->b);
00259          a[j]->type= STD_ITEM;
00260        }
00261        else if (a[j]->type != CONTROL_ITEM) break;
00262       }
00263   }
00264 }
00265 
00266 void
00267 concater_rep::handle_brackets () {
00268   int first=-1, start=0, i=0;
00269   while (i<N(a)) {
00270     if (a[i]->type==LEFT_BRACKET_ITEM) {
00271       if (first==-1) first= i;
00272       start= i;
00273     }
00274     if (a[i]->type==RIGHT_BRACKET_ITEM) {
00275       handle_scripts  (succ (start), prec (i));
00276       handle_matching (start, i);
00277       if (first!=-1) i=first-1;
00278       start= 0;
00279       first= -1;
00280     }
00281     i++;
00282   }
00283   if (N(a)>0) {
00284     handle_scripts  (0, N(a)-1);
00285     handle_matching (0, N(a)-1);
00286   }
00287 }
00288 
00289 /******************************************************************************
00290 * Kill invalid spaces
00291 ******************************************************************************/
00292 
00293 void
00294 concater_rep::kill_spaces () {
00295   int i;
00296   for (i=N(a)-1; (i>0) && (a[i]->type == CONTROL_ITEM); i--)
00297     a[i-1]->spc= space (0);
00298   for (i=0; (i<N(a)) && (a[i]->type == CONTROL_ITEM); i++)
00299     a[i]->spc= space (0);
00300 
00301   for (i=0; i<N(a); i++)
00302     if (a[i]->type==CONTROL_ITEM) {
00303       if (is_formatting (a[i]->t)) {
00304        tree_label lab= L(a[i]->t);
00305        if ((lab==NEXT_LINE) || (lab==LINE_BREAK) || (lab==NEW_LINE))
00306          {
00307            if (i>0) a[i-1]->spc= space (0);
00308            a[i]->spc= space (0);
00309          }
00310       }
00311 
00312       if (is_tuple (a[i]->t, "env_par") ||
00313          is_tuple (a[i]->t, "env_page"))
00314        a[i]->spc= space (0);
00315     }
00316 }
00317 
00318 /******************************************************************************
00319 * Main control
00320 ******************************************************************************/
00321 
00322 void
00323 concater_rep::finish () {
00324   kill_spaces ();
00325   pre_glue ();
00326   handle_brackets ();
00327   clean_and_correct ();
00328 }