LCOV - code coverage report
Current view: top level - preproc/eqn - sqrt.cpp (source / functions) Hit Total Coverage
Test: GNU roff Lines: 62 73 84.9 %
Date: 2026-01-16 17:51:41 Functions: 5 6 83.3 %
Legend: Lines: hit not hit

          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:

Generated by: LCOV version 1.14