Line data Source code
1 : /* Copyright 1989-2024 Free Software Foundation, Inc.
2 : Written by James Clark (jjc@jclark.com)
3 :
4 : This file is part of groff, the GNU roff typesetting system.
5 :
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 3 of the License, or
9 : (at your option) any later version.
10 :
11 : groff is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 :
19 : #ifdef HAVE_CONFIG_H
20 : #include <config.h>
21 : #endif
22 :
23 : #include "eqn.h"
24 : #include "pbox.h"
25 :
26 : class sqrt_box : public pointer_box {
27 : public:
28 : sqrt_box(box *);
29 : int compute_metrics(int style);
30 : void output();
31 : void debug_print();
32 : void diagnose_tab_stop_usage(int);
33 : };
34 :
35 8 : box *make_sqrt_box(box *pp)
36 : {
37 8 : return new sqrt_box(pp);
38 : }
39 :
40 8 : sqrt_box::sqrt_box(box *pp) : pointer_box(pp)
41 : {
42 8 : }
43 :
44 : #define SQRT_CHAR "\\[sqrt]"
45 : #define RADICAL_EXTENSION_CHAR "\\[sqrtex]"
46 :
47 : #define SQRT_CHAIN "\\[sqrt\\\\n[" INDEX_REG "]]"
48 : #define BAR_CHAIN "\\[sqrtex\\\\n[" INDEX_REG "]]"
49 :
50 8 : int sqrt_box::compute_metrics(int style)
51 : {
52 : // 11
53 8 : int r = p->compute_metrics(cramped_style(style));
54 16 : printf(".nr " TEMP_REG " \\n[" HEIGHT_FORMAT "]+\\n[" DEPTH_FORMAT
55 : "]+%dM+(%dM/4)\n",
56 8 : p->uid, p->uid, get_param("default_rule_thickness"),
57 8 : (style > SCRIPT_STYLE ? get_param("x_height")
58 0 : : get_param("default_rule_thickness")));
59 8 : printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
60 8 : printf(".ds " SQRT_STRING_FORMAT " " SQRT_CHAR "\n", uid);
61 8 : printf(".ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n");
62 8 : printf(".nr " SQRT_WIDTH_FORMAT
63 : " 0\\w" DELIMITER_CHAR SQRT_CHAR DELIMITER_CHAR "\n",
64 8 : uid);
65 8 : printf(".if \\n[rst]-\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{",
66 : get_param("default_rule_thickness"));
67 :
68 8 : printf(".nr " INDEX_REG " 0\n"
69 : ".de " TEMP_MACRO "\n"
70 : ".ie c" SQRT_CHAIN " \\{"
71 : ".ds " SQRT_STRING_FORMAT " " SQRT_CHAIN "\n"
72 : ".ie c" BAR_CHAIN " .ds " BAR_STRING " " BAR_CHAIN "\n"
73 : ".el .ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n"
74 : ".nr " SQRT_WIDTH_FORMAT
75 : " 0\\w" DELIMITER_CHAR SQRT_CHAIN DELIMITER_CHAR "\n"
76 : ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{"
77 : ".nr " INDEX_REG " +1\n"
78 : "." TEMP_MACRO "\n"
79 : ".\\}\\}\n"
80 : ".el .nr " INDEX_REG " 0-1\n"
81 : "..\n"
82 : "." TEMP_MACRO "\n",
83 8 : uid, uid, get_param("default_rule_thickness"));
84 :
85 8 : printf(".if \\n[" INDEX_REG "]<0 \\{");
86 :
87 : // Determine the maximum point size
88 8 : printf(".ps 1000\n");
89 8 : printf(".nr " MAX_SIZE_REG " \\n[.ps]\n");
90 8 : printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
91 : // We define a macro that will increase the current point size
92 : // until we get a radical sign that's tall enough or we reach
93 : // the maximum point size.
94 8 : printf(".de " TEMP_MACRO "\n"
95 : ".nr " SQRT_WIDTH_FORMAT
96 : " 0\\w" DELIMITER_CHAR "\\*[" SQRT_STRING_FORMAT "]" DELIMITER_CHAR "\n"
97 : ".if \\\\n[rst]"
98 : "&(\\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "])"
99 : "&(\\\\n[.ps]<\\n[" MAX_SIZE_REG "]) \\{"
100 : ".ps +1\n"
101 : "." TEMP_MACRO "\n"
102 : ".\\}\n"
103 : "..\n"
104 : "." TEMP_MACRO "\n",
105 8 : uid, uid, get_param("default_rule_thickness"));
106 :
107 8 : printf(".\\}\\}\n");
108 :
109 8 : printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
110 : // set TEMP_REG to the amount by which the radical sign is too big
111 8 : printf(".nr " TEMP_REG " \\n[rst]-\\n[rsb]-%dM-\\n[" TEMP_REG "]\n",
112 : get_param("default_rule_thickness"));
113 : // If TEMP_REG is negative, the bottom of the radical sign should
114 : // be -TEMP_REG above the bottom of p. If it's positive, the bottom
115 : // of the radical sign should be TEMP_REG/2 below the bottom of p.
116 : // This calculates the amount by which the baseline of the radical
117 : // should be raised.
118 8 : printf(".nr " SUP_RAISE_FORMAT " (-\\n[" TEMP_REG "]>?(-\\n[" TEMP_REG "]/2))"
119 8 : "-\\n[rsb]-\\n[" DEPTH_FORMAT "]\n", uid, p->uid);
120 8 : printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
121 : ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
122 8 : uid, p->uid, uid);
123 8 : printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
124 : ">?(-\\n[" SUP_RAISE_FORMAT "]-\\n[rsb])\n",
125 8 : uid, p->uid, uid);
126 : // Do this last, so we don't lose height and depth information on
127 : // the radical sign.
128 : // Remember that the width of the bar might be greater than the width of p.
129 :
130 8 : printf(".nr " TEMP_REG " "
131 : "\\n[" WIDTH_FORMAT "]"
132 : ">?\\w" DELIMITER_CHAR "\\*[" BAR_STRING "]" DELIMITER_CHAR "\n",
133 8 : p->uid);
134 8 : printf(".as " SQRT_STRING_FORMAT " "
135 : "\\l'\\n[" TEMP_REG "]u\\&\\*[" BAR_STRING "]'\n",
136 8 : uid);
137 8 : printf(".nr " WIDTH_FORMAT " \\n[" TEMP_REG "]"
138 : "+\\n[" SQRT_WIDTH_FORMAT "]\n",
139 8 : uid, uid);
140 :
141 8 : if (r)
142 0 : printf(".nr " MARK_REG " +\\n[" SQRT_WIDTH_FORMAT "]\n", uid);
143 : // the top of the bar might be higher than the top of the radical sign
144 8 : printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
145 : ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
146 8 : uid, p->uid, uid);
147 : // put a bit of extra space above the bar
148 8 : printf(".nr " HEIGHT_FORMAT " +%dM\n", uid,
149 : get_param("default_rule_thickness"));
150 8 : printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
151 8 : return r;
152 : }
153 :
154 8 : void sqrt_box::output()
155 : {
156 8 : if (output_format == troff) {
157 8 : printf("\\Z" DELIMITER_CHAR);
158 8 : printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
159 8 : printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
160 8 : printf("\\*[" SQRT_STRING_FORMAT "]", uid);
161 8 : printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
162 8 : printf(DELIMITER_CHAR);
163 :
164 8 : printf("\\Z" DELIMITER_CHAR);
165 8 : printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u"
166 : "+\\n[" SQRT_WIDTH_FORMAT "]u/2u'",
167 8 : uid, p->uid, uid);
168 8 : p->output();
169 8 : printf(DELIMITER_CHAR);
170 :
171 8 : printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
172 : }
173 0 : else if (output_format == mathml) {
174 0 : printf("<msqrt>");
175 0 : p->output();
176 0 : printf("</msqrt>");
177 : }
178 8 : }
179 :
180 0 : void sqrt_box::debug_print()
181 : {
182 0 : fprintf(stderr, "sqrt { ");
183 0 : p->debug_print();
184 0 : fprintf(stderr, " }");
185 0 : }
186 :
187 8 : void sqrt_box::diagnose_tab_stop_usage(int level)
188 : {
189 8 : p->diagnose_tab_stop_usage(level + 1);
190 8 : }
191 :
192 : // Local Variables:
193 : // fill-column: 72
194 : // mode: C++
195 : // End:
196 : // vim: set cindent noexpandtab shiftwidth=2 textwidth=72:
|