Home | History | Annotate | Line # | Download | only in eqn
      1 /*	$NetBSD: sqrt.cpp,v 1.1.1.1 2016/01/13 18:41:49 christos Exp $	*/
      2 
      3 // -*- C++ -*-
      4 /* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2003
      5    Free Software Foundation, Inc.
      6      Written by James Clark (jjc (at) jclark.com)
      7 
      8 This file is part of groff.
      9 
     10 groff is free software; you can redistribute it and/or modify it under
     11 the terms of the GNU General Public License as published by the Free
     12 Software Foundation; either version 2, or (at your option) any later
     13 version.
     14 
     15 groff is distributed in the hope that it will be useful, but WITHOUT ANY
     16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
     17 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     18 for more details.
     19 
     20 You should have received a copy of the GNU General Public License along
     21 with groff; see the file COPYING.  If not, write to the Free Software
     22 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
     23 
     24 #include "eqn.h"
     25 #include "pbox.h"
     26 
     27 
     28 class sqrt_box : public pointer_box {
     29 public:
     30   sqrt_box(box *);
     31   int compute_metrics(int style);
     32   void output();
     33   void debug_print();
     34   void check_tabs(int);
     35 };
     36 
     37 box *make_sqrt_box(box *pp)
     38 {
     39   return new sqrt_box(pp);
     40 }
     41 
     42 sqrt_box::sqrt_box(box *pp) : pointer_box(pp)
     43 {
     44 }
     45 
     46 #define SQRT_CHAR "\\[sqrt]"
     47 #define RADICAL_EXTENSION_CHAR "\\[sqrtex]"
     48 
     49 #define SQRT_CHAIN "\\[sqrt\\\\n[" INDEX_REG "]]"
     50 #define BAR_CHAIN "\\[sqrtex\\\\n[" INDEX_REG "]]"
     51 
     52 int sqrt_box::compute_metrics(int style)
     53 {
     54   // 11
     55   int r = p->compute_metrics(cramped_style(style));
     56   printf(".nr " TEMP_REG " \\n[" HEIGHT_FORMAT "]+\\n[" DEPTH_FORMAT
     57 	 "]+%dM+(%dM/4)\n",
     58 	 p->uid, p->uid, default_rule_thickness,
     59 	 (style > SCRIPT_STYLE ? x_height : default_rule_thickness));
     60   printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
     61   printf(".ds " SQRT_STRING_FORMAT " " SQRT_CHAR "\n", uid);
     62   printf(".ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n");
     63   printf(".nr " SQRT_WIDTH_FORMAT
     64 	 " 0\\w" DELIMITER_CHAR SQRT_CHAR DELIMITER_CHAR "\n",
     65 	 uid);
     66   printf(".if \\n[rst]-\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{",
     67 	 default_rule_thickness);
     68 
     69   printf(".nr " INDEX_REG " 0\n"
     70 	 ".de " TEMP_MACRO "\n"
     71 	 ".ie c" SQRT_CHAIN " \\{"
     72 	 ".ds " SQRT_STRING_FORMAT " " SQRT_CHAIN "\n"
     73 	 ".ie c" BAR_CHAIN " .ds " BAR_STRING " " BAR_CHAIN "\n"
     74 	 ".el .ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n"
     75 	 ".nr " SQRT_WIDTH_FORMAT
     76 	 " 0\\w" DELIMITER_CHAR SQRT_CHAIN DELIMITER_CHAR "\n"
     77 	 ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{"
     78 	 ".nr " INDEX_REG " +1\n"
     79 	 "." TEMP_MACRO "\n"
     80 	 ".\\}\\}\n"
     81 	 ".el .nr " INDEX_REG " 0-1\n"
     82 	 "..\n"
     83 	 "." TEMP_MACRO "\n",
     84 	 uid, uid, default_rule_thickness);
     85 
     86   printf(".if \\n[" INDEX_REG "]<0 \\{");
     87 
     88   // Determine the maximum point size
     89   printf(".ps 1000\n");
     90   printf(".nr " MAX_SIZE_REG " \\n[.ps]\n");
     91   printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
     92   // We define a macro that will increase the current point size
     93   // until we get a radical sign that's tall enough or we reach
     94   // the maximum point size.
     95   printf(".de " TEMP_MACRO "\n"
     96 	 ".nr " SQRT_WIDTH_FORMAT
     97 	 " 0\\w" DELIMITER_CHAR "\\*[" SQRT_STRING_FORMAT "]" DELIMITER_CHAR "\n"
     98 	 ".if \\\\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 	 uid, uid, default_rule_thickness);
    106 
    107   printf(".\\}\\}\n");
    108 
    109   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   printf(".nr " TEMP_REG " \\n[rst]-\\n[rsb]-%dM-\\n[" TEMP_REG "]\n",
    112 	 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   printf(".nr " SUP_RAISE_FORMAT " (-\\n[" TEMP_REG "]>?(-\\n[" TEMP_REG "]/2))"
    119 	 "-\\n[rsb]-\\n[" DEPTH_FORMAT "]\n", uid, p->uid);
    120   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
    121 	 ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
    122 	 uid, p->uid, uid);
    123   printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
    124 	 ">?(-\\n[" SUP_RAISE_FORMAT "]-\\n[rsb])\n",
    125 	 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   printf(".nr " TEMP_REG " "
    131 	 "\\n[" WIDTH_FORMAT "]"
    132 	 ">?\\w" DELIMITER_CHAR "\\*[" BAR_STRING "]" DELIMITER_CHAR "\n",
    133 	 p->uid);
    134   printf(".as " SQRT_STRING_FORMAT " "
    135 	 "\\l'\\n[" TEMP_REG "]u\\&\\*[" BAR_STRING "]'\n",
    136 	 uid);
    137   printf(".nr " WIDTH_FORMAT " \\n[" TEMP_REG "]"
    138 	 "+\\n[" SQRT_WIDTH_FORMAT "]\n",
    139 	 uid, uid);
    140 
    141   if (r)
    142     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   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
    145 	 ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
    146 	 uid, p->uid, uid);
    147   // put a bit of extra space above the bar
    148   printf(".nr " HEIGHT_FORMAT " +%dM\n", uid, default_rule_thickness);
    149   printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
    150   return r;
    151 }
    152 
    153 void sqrt_box::output()
    154 {
    155   printf("\\Z" DELIMITER_CHAR);
    156   printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
    157   printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
    158   printf("\\*[" SQRT_STRING_FORMAT "]", uid);
    159   printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
    160   printf(DELIMITER_CHAR);
    161 
    162   printf("\\Z" DELIMITER_CHAR);
    163   printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u"
    164 	 "+\\n[" SQRT_WIDTH_FORMAT "]u/2u'",
    165 	 uid, p->uid, uid);
    166   p->output();
    167   printf(DELIMITER_CHAR);
    168 
    169   printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
    170 }
    171 
    172 void sqrt_box::debug_print()
    173 {
    174   fprintf(stderr, "sqrt { ");
    175   p->debug_print();
    176   fprintf(stderr, " }");
    177 }
    178 
    179 void sqrt_box::check_tabs(int level)
    180 {
    181   p->check_tabs(level + 1);
    182 }
    183