PageRenderTime 215ms CodeModel.GetById 55ms RepoModel.GetById 2ms app.codeStats 0ms

/TeXmacs-1.0.7.11-src/src/Typeset/Concat/concat_post.cpp

#
C++ | 328 lines | 265 code | 28 blank | 35 comment | 117 complexity | 0b9b591aa3911c60a91fa06e270d6b23 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. /******************************************************************************
  2. * MODULE : concat_post.cpp
  3. * DESCRIPTION: Second pass for typesetting paragraphs
  4. * - The real heights of brackets are determined
  5. * - scripts are glued
  6. * COPYRIGHT : (C) 1999 Joris van der Hoeven
  7. *******************************************************************************
  8. * This software falls under the GNU general public license version 3 or later.
  9. * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
  10. * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
  11. ******************************************************************************/
  12. #include "concater.hpp"
  13. SI italic_correction (box, box);
  14. /******************************************************************************
  15. * Miscellaneous routines
  16. ******************************************************************************/
  17. int
  18. concater_rep::prec (int i) {
  19. do i--; while ((i>=0) && (a[i]->type==OBSOLETE_ITEM));
  20. return i;
  21. }
  22. int
  23. concater_rep::succ (int i) {
  24. do i++; while ((i<N(a)) && (a[i]->type==OBSOLETE_ITEM));
  25. return i;
  26. }
  27. /******************************************************************************
  28. * Gluing scripts
  29. ******************************************************************************/
  30. void
  31. concater_rep::pre_glue () {
  32. int i;
  33. for (i=0; i<N(a)-1; i++) {
  34. line_item item1= a[i];
  35. line_item item2= a[i+1];
  36. int t1= item1->type;
  37. int t2= item2->type;
  38. if (((t1 == RSUB_ITEM) && (t2 == RSUP_ITEM)) ||
  39. ((t1 == RSUP_ITEM) && (t2 == RSUB_ITEM)) ||
  40. ((t1 == LSUB_ITEM) && (t2 == LSUP_ITEM)) ||
  41. ((t1 == LSUP_ITEM) && (t2 == LSUB_ITEM)))
  42. {
  43. bool flag1 = (t1 == LSUB_ITEM) || (t1 == RSUB_ITEM);
  44. bool flag2 = (t1 == LSUB_ITEM) || (t1 == LSUP_ITEM);
  45. int type = flag2? GLUE_LSUBS_ITEM: GLUE_RSUBS_ITEM;
  46. box b1 = flag1? item1->b[0]: item2->b[0];
  47. box b2 = flag1? item2->b[0]: item1->b[0];
  48. box b = script_box (b1->ip, b1, b2, env->fn);
  49. int pen = item2->penalty;
  50. space spc = max (item1->spc, item2->spc);
  51. a[i]= line_item (type, OP_SKIP, b, pen);
  52. a[i]->spc = spc;
  53. a[i+1]= line_item (OBSOLETE_ITEM, OP_SKIP, item2->b, pen);
  54. }
  55. }
  56. }
  57. void
  58. concater_rep::glue (box b, int ref, int arg) {
  59. space spc = max (a[ref]->spc, a[arg]->spc);
  60. a[arg] = line_item (OBSOLETE_ITEM, OP_SKIP, a[arg]->b, a[arg]->penalty);
  61. a[ref] = line_item (arg<ref? GLUE_LEFT_ITEM: GLUE_RIGHT_ITEM,
  62. a[ref]->op_type, b,
  63. min (a[ref]->penalty, a[arg]->penalty));
  64. a[ref]->spc = spc;
  65. }
  66. void
  67. concater_rep::glue (box b, int ref, int arg1, int arg2) {
  68. space spc = max (a[ref]->spc, max (a[arg1]->spc, a[arg2]->spc));
  69. int pen = min (a[ref]->penalty, min (a[arg1]->penalty, a[arg2]->penalty));
  70. space ref_spc= a[ref]->spc;
  71. a[arg1]= line_item (OBSOLETE_ITEM, OP_SKIP, a[arg1]->b, a[arg1]->penalty);
  72. a[arg2]= line_item (OBSOLETE_ITEM, OP_SKIP, a[arg2]->b, a[arg2]->penalty);
  73. a[ref]= line_item (GLUE_BOTH_ITEM, a[ref]->op_type, b, pen);
  74. a[ref]->spc = spc;
  75. }
  76. void
  77. concater_rep::handle_scripts (int start, int end) {
  78. int i;
  79. for (i=start; i<=end; ) {
  80. if ((a[i]->type == OBSOLETE_ITEM) ||
  81. (a[i]->type == LSUB_ITEM) ||
  82. (a[i]->type == LSUP_ITEM) ||
  83. (a[i]->type == GLUE_LSUBS_ITEM) ||
  84. (a[i]->type == RSUB_ITEM) ||
  85. (a[i]->type == RSUP_ITEM) ||
  86. (a[i]->type == GLUE_RSUBS_ITEM)) { i++; continue; }
  87. path sip;
  88. int l= prec (i);
  89. box lb1, lb2;
  90. if (l < start) l= -1;
  91. else switch (a[l]->type) {
  92. case LSUB_ITEM:
  93. lb1= a[l]->b[0];
  94. sip= lb1->ip;
  95. break;
  96. case LSUP_ITEM:
  97. lb2= a[l]->b[0];
  98. sip= lb2->ip;
  99. break;
  100. case GLUE_LSUBS_ITEM:
  101. lb1= a[l]->b[0];
  102. lb2= a[l]->b[1];
  103. sip= lb2->ip;
  104. break;
  105. default:
  106. l = -1;
  107. }
  108. int r= succ (i);
  109. box rb1, rb2;
  110. if (r > end) r= N(a);
  111. else switch (a[r]->type) {
  112. case RSUB_ITEM:
  113. rb1= a[r]->b[0];
  114. sip= rb1->ip;
  115. break;
  116. case RSUP_ITEM:
  117. rb2= a[r]->b[0];
  118. sip= rb2->ip;
  119. break;
  120. case GLUE_RSUBS_ITEM:
  121. rb1= a[r]->b[0];
  122. rb2= a[r]->b[1];
  123. sip= rb2->ip;
  124. break;
  125. default:
  126. r = N(a);
  127. }
  128. box b;
  129. if ((l==-1) && (r==N(a))) { i++; continue; }
  130. if ((l!=-1) && (r==N(a))) {
  131. b= left_script_box (sip, a[i]->b, lb1, lb2, env->fn, env->vert_pos);
  132. glue (b, i, l);
  133. }
  134. if ((l==-1) && (r!=N(a))) {
  135. if (a[i]->limits)
  136. b= limit_box (sip, a[i]->b, rb1, rb2, env->fn, true);
  137. else
  138. b= right_script_box (sip, a[i]->b, rb1, rb2, env->fn, env->vert_pos);
  139. glue (b, i, r);
  140. }
  141. if ((l!=-1) && (r!=N(a))) {
  142. b= side_box (sip, a[i]->b, lb1, lb2, rb1, rb2, env->fn, env->vert_pos);
  143. glue (b, i, l, r);
  144. }
  145. }
  146. }
  147. void
  148. concater_rep::clean_and_correct () {
  149. array<line_item> new_a;
  150. int i, prev=-1;
  151. for (i=0; i<N(a); i++)
  152. if (a[i]->type!=OBSOLETE_ITEM) {
  153. if (a[i]->b->w () != 0) {
  154. if (prev != -1)
  155. a[prev]->spc += space (::italic_correction (a[prev]->b, a[i]->b));
  156. prev= i;
  157. }
  158. new_a << a[i];
  159. }
  160. a= new_a;
  161. }
  162. /******************************************************************************
  163. * Resize brackets
  164. ******************************************************************************/
  165. void
  166. concater_rep::handle_matching (int start, int end) {
  167. //cout << "matching " << start << " -- " << end << "\n";
  168. //cout << a << "\n\n";
  169. int i;
  170. SI y1= min (a[start]->b->y1, a[end]->b->y2);
  171. SI y2= max (a[start]->b->y1, a[end]->b->y2);
  172. a[start]->penalty++;
  173. a[end]->penalty++;
  174. // cout << "Start: " << (y2-y1) << "\n";
  175. for (i=start+1; i<end; i++) {
  176. if (a[i]->type == OBSOLETE_ITEM) continue;
  177. // cout << " " << a[i] << ": " << (a[i]->b->y2- a[i]->b->y1) << "\n";
  178. // y1= min (y1, a[i]->b->sub_base());
  179. // y2= max (y2, a[i]->b->sup_base());
  180. y1= min (y1, a[i]->b->y1);
  181. y2= max (y2, a[i]->b->y2);
  182. a[i]->penalty++;
  183. }
  184. for (i=start; i<=end; i++) {
  185. int tp= a[i]->type;
  186. if (tp == LEFT_BRACKET_ITEM ||
  187. tp == MIDDLE_BRACKET_ITEM ||
  188. tp == RIGHT_BRACKET_ITEM)
  189. {
  190. // make symmetric and prevent from too large delimiters if possible
  191. font fn = a[i]->b->get_leaf_font ();
  192. SI Y1 = y1 + (fn->sep >> 1);
  193. SI Y2 = y2 - (fn->sep >> 1);
  194. SI tol = fn->sep << 1;
  195. SI mid = (a[i]->b->y1 + a[i]->b->y2) >> 1;
  196. SI drift= ((Y1 + Y2) >> 1) - mid; // fn->yfrac;
  197. if (drift < 0) Y2 += min (-drift, tol) << 1;
  198. else Y1 -= min (drift, tol) << 1;
  199. // further adjustments when the enclosed expression is not very heigh
  200. SI h= y2 - y1 - fn->sep;
  201. SI d= 5 * fn->yx - h;
  202. if (d > 0) { Y1 += d/12; Y2 -= d/12; }
  203. // replace item by large or small delimiter
  204. string ls= a[i]->b->get_leaf_string ();
  205. color lc= a[i]->b->get_leaf_color ();
  206. font lf= a[i]->b->get_leaf_font ();
  207. if (Y1 < fn->y1 || Y2 > fn->y2)
  208. a[i]->b= delimiter_box (a[i]->b->ip, ls, fn, lc, Y1, Y2);
  209. else {
  210. string s= "<nobracket>";
  211. int j;
  212. for (j=0; j<N(ls); j++)
  213. if (ls[j] == '-') break;
  214. if (j<N(ls) && ls[N(ls)-1] == '>') s= ls (j+1, N(ls)-1);
  215. if (N(s) != 1 && s[0] != '<') s= "<" * s * ">";
  216. else if (s == ".") s= "<nobracket>";
  217. a[i]->b= text_box (a[i]->b->ip, 0, s, lf, lc);
  218. tp= STD_ITEM;
  219. }
  220. a[i]->type= STD_ITEM;
  221. }
  222. if (tp == LEFT_BRACKET_ITEM)
  223. for (int j= i-1; j>=0; j--) {
  224. if (a[j]->type == MARKER_ITEM) {
  225. SI Y1= a[i]->b->y1;
  226. SI Y2= a[i]->b->y2;
  227. a[j]->b = marker_box (a[j]->b->find_lip (), 0, Y1, 0, Y2, a[j]->b);
  228. a[j]->type= STD_ITEM;
  229. }
  230. else if (a[j]->type != CONTROL_ITEM) break;
  231. }
  232. if (tp == RIGHT_BRACKET_ITEM)
  233. for (int j= i+1; j<N(a); j++) {
  234. if (a[j]->type == MARKER_ITEM) {
  235. SI Y1= a[i]->b->y1;
  236. SI Y2= a[i]->b->y2;
  237. a[j]->b = marker_box (a[j]->b->find_lip (), 0, Y1, 0, Y2, a[j]->b);
  238. a[j]->type= STD_ITEM;
  239. }
  240. else if (a[j]->type != CONTROL_ITEM) break;
  241. }
  242. }
  243. }
  244. void
  245. concater_rep::handle_brackets () {
  246. int first=-1, start=0, i=0;
  247. while (i<N(a)) {
  248. if (a[i]->type==LEFT_BRACKET_ITEM) {
  249. if (first==-1) first= i;
  250. start= i;
  251. }
  252. if (a[i]->type==RIGHT_BRACKET_ITEM) {
  253. handle_scripts (succ (start), prec (i));
  254. handle_matching (start, i);
  255. if (first!=-1) i=first-1;
  256. start= 0;
  257. first= -1;
  258. }
  259. i++;
  260. }
  261. if (N(a)>0) {
  262. handle_scripts (0, N(a)-1);
  263. handle_matching (0, N(a)-1);
  264. }
  265. }
  266. /******************************************************************************
  267. * Kill invalid spaces
  268. ******************************************************************************/
  269. void
  270. concater_rep::kill_spaces () {
  271. int i;
  272. for (i=N(a)-1; (i>0) && (a[i]->type == CONTROL_ITEM); i--)
  273. a[i-1]->spc= space (0);
  274. for (i=0; (i<N(a)) && (a[i]->type == CONTROL_ITEM); i++)
  275. a[i]->spc= space (0);
  276. for (i=0; i<N(a); i++)
  277. if (a[i]->type==CONTROL_ITEM) {
  278. if (is_formatting (a[i]->t)) {
  279. tree_label lab= L(a[i]->t);
  280. if ((lab==NEXT_LINE) || (lab==LINE_BREAK) || (lab==NEW_LINE))
  281. {
  282. if (i>0) a[i-1]->spc= space (0);
  283. a[i]->spc= space (0);
  284. }
  285. }
  286. if (is_tuple (a[i]->t, "env_par") ||
  287. is_tuple (a[i]->t, "env_page"))
  288. a[i]->spc= space (0);
  289. }
  290. }
  291. /******************************************************************************
  292. * Main control
  293. ******************************************************************************/
  294. void
  295. concater_rep::finish () {
  296. kill_spaces ();
  297. pre_glue ();
  298. handle_brackets ();
  299. clean_and_correct ();
  300. }