/contrib/groff/src/preproc/eqn/sqrt.cpp

https://bitbucket.org/freebsd/freebsd-head/ · C++ · 180 lines · 124 code · 20 blank · 36 comment · 1 complexity · 13f1f69c2a6255fc5e9f161f69a0835c MD5 · raw file

  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2003
  3. Free Software Foundation, Inc.
  4. Written by James Clark (jjc@jclark.com)
  5. This file is part of groff.
  6. groff is free software; you can redistribute it and/or modify it under
  7. the terms of the GNU General Public License as published by the Free
  8. Software Foundation; either version 2, or (at your option) any later
  9. version.
  10. groff is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  13. for more details.
  14. You should have received a copy of the GNU General Public License along
  15. with groff; see the file COPYING. If not, write to the Free Software
  16. Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
  17. #include "eqn.h"
  18. #include "pbox.h"
  19. class sqrt_box : public pointer_box {
  20. public:
  21. sqrt_box(box *);
  22. int compute_metrics(int style);
  23. void output();
  24. void debug_print();
  25. void check_tabs(int);
  26. };
  27. box *make_sqrt_box(box *pp)
  28. {
  29. return new sqrt_box(pp);
  30. }
  31. sqrt_box::sqrt_box(box *pp) : pointer_box(pp)
  32. {
  33. }
  34. #define SQRT_CHAR "\\[sqrt]"
  35. #define RADICAL_EXTENSION_CHAR "\\[sqrtex]"
  36. #define SQRT_CHAIN "\\[sqrt\\\\n[" INDEX_REG "]]"
  37. #define BAR_CHAIN "\\[sqrtex\\\\n[" INDEX_REG "]]"
  38. int sqrt_box::compute_metrics(int style)
  39. {
  40. // 11
  41. int r = p->compute_metrics(cramped_style(style));
  42. printf(".nr " TEMP_REG " \\n[" HEIGHT_FORMAT "]+\\n[" DEPTH_FORMAT
  43. "]+%dM+(%dM/4)\n",
  44. p->uid, p->uid, default_rule_thickness,
  45. (style > SCRIPT_STYLE ? x_height : default_rule_thickness));
  46. printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
  47. printf(".ds " SQRT_STRING_FORMAT " " SQRT_CHAR "\n", uid);
  48. printf(".ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n");
  49. printf(".nr " SQRT_WIDTH_FORMAT
  50. " 0\\w" DELIMITER_CHAR SQRT_CHAR DELIMITER_CHAR "\n",
  51. uid);
  52. printf(".if \\n[rst]-\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{",
  53. default_rule_thickness);
  54. printf(".nr " INDEX_REG " 0\n"
  55. ".de " TEMP_MACRO "\n"
  56. ".ie c" SQRT_CHAIN " \\{"
  57. ".ds " SQRT_STRING_FORMAT " " SQRT_CHAIN "\n"
  58. ".ie c" BAR_CHAIN " .ds " BAR_STRING " " BAR_CHAIN "\n"
  59. ".el .ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n"
  60. ".nr " SQRT_WIDTH_FORMAT
  61. " 0\\w" DELIMITER_CHAR SQRT_CHAIN DELIMITER_CHAR "\n"
  62. ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{"
  63. ".nr " INDEX_REG " +1\n"
  64. "." TEMP_MACRO "\n"
  65. ".\\}\\}\n"
  66. ".el .nr " INDEX_REG " 0-1\n"
  67. "..\n"
  68. "." TEMP_MACRO "\n",
  69. uid, uid, default_rule_thickness);
  70. printf(".if \\n[" INDEX_REG "]<0 \\{");
  71. // Determine the maximum point size
  72. printf(".ps 1000\n");
  73. printf(".nr " MAX_SIZE_REG " \\n[.ps]\n");
  74. printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
  75. // We define a macro that will increase the current point size
  76. // until we get a radical sign that's tall enough or we reach
  77. // the maximum point size.
  78. printf(".de " TEMP_MACRO "\n"
  79. ".nr " SQRT_WIDTH_FORMAT
  80. " 0\\w" DELIMITER_CHAR "\\*[" SQRT_STRING_FORMAT "]" DELIMITER_CHAR "\n"
  81. ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "]"
  82. "&(\\\\n[.ps]<\\n[" MAX_SIZE_REG "]) \\{"
  83. ".ps +1\n"
  84. "." TEMP_MACRO "\n"
  85. ".\\}\n"
  86. "..\n"
  87. "." TEMP_MACRO "\n",
  88. uid, uid, default_rule_thickness);
  89. printf(".\\}\\}\n");
  90. printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
  91. // set TEMP_REG to the amount by which the radical sign is too big
  92. printf(".nr " TEMP_REG " \\n[rst]-\\n[rsb]-%dM-\\n[" TEMP_REG "]\n",
  93. default_rule_thickness);
  94. // If TEMP_REG is negative, the bottom of the radical sign should
  95. // be -TEMP_REG above the bottom of p. If it's positive, the bottom
  96. // of the radical sign should be TEMP_REG/2 below the bottom of p.
  97. // This calculates the amount by which the baseline of the radical
  98. // should be raised.
  99. printf(".nr " SUP_RAISE_FORMAT " (-\\n[" TEMP_REG "]>?(-\\n[" TEMP_REG "]/2))"
  100. "-\\n[rsb]-\\n[" DEPTH_FORMAT "]\n", uid, p->uid);
  101. printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
  102. ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
  103. uid, p->uid, uid);
  104. printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
  105. ">?(-\\n[" SUP_RAISE_FORMAT "]-\\n[rsb])\n",
  106. uid, p->uid, uid);
  107. // Do this last, so we don't lose height and depth information on
  108. // the radical sign.
  109. // Remember that the width of the bar might be greater than the width of p.
  110. printf(".nr " TEMP_REG " "
  111. "\\n[" WIDTH_FORMAT "]"
  112. ">?\\w" DELIMITER_CHAR "\\*[" BAR_STRING "]" DELIMITER_CHAR "\n",
  113. p->uid);
  114. printf(".as " SQRT_STRING_FORMAT " "
  115. "\\l'\\n[" TEMP_REG "]u\\&\\*[" BAR_STRING "]'\n",
  116. uid);
  117. printf(".nr " WIDTH_FORMAT " \\n[" TEMP_REG "]"
  118. "+\\n[" SQRT_WIDTH_FORMAT "]\n",
  119. uid, uid);
  120. if (r)
  121. printf(".nr " MARK_REG " +\\n[" SQRT_WIDTH_FORMAT "]\n", uid);
  122. // the top of the bar might be higher than the top of the radical sign
  123. printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
  124. ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
  125. uid, p->uid, uid);
  126. // put a bit of extra space above the bar
  127. printf(".nr " HEIGHT_FORMAT " +%dM\n", uid, default_rule_thickness);
  128. printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
  129. return r;
  130. }
  131. void sqrt_box::output()
  132. {
  133. printf("\\Z" DELIMITER_CHAR);
  134. printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
  135. printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
  136. printf("\\*[" SQRT_STRING_FORMAT "]", uid);
  137. printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
  138. printf(DELIMITER_CHAR);
  139. printf("\\Z" DELIMITER_CHAR);
  140. printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u"
  141. "+\\n[" SQRT_WIDTH_FORMAT "]u/2u'",
  142. uid, p->uid, uid);
  143. p->output();
  144. printf(DELIMITER_CHAR);
  145. printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
  146. }
  147. void sqrt_box::debug_print()
  148. {
  149. fprintf(stderr, "sqrt { ");
  150. p->debug_print();
  151. fprintf(stderr, " }");
  152. }
  153. void sqrt_box::check_tabs(int level)
  154. {
  155. p->check_tabs(level + 1);
  156. }