diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:44:05 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:44:05 +0000 |
commit | d318611dd6f23fcfedd50e9b9e24620b102ba96a (patch) | |
tree | 8b9eef82ca40fdd5a8deeabf07572074c236095d /src/preproc/eqn/sqrt.cpp | |
parent | Initial commit. (diff) | |
download | groff-d318611dd6f23fcfedd50e9b9e24620b102ba96a.tar.xz groff-d318611dd6f23fcfedd50e9b9e24620b102ba96a.zip |
Adding upstream version 1.23.0.upstream/1.23.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/preproc/eqn/sqrt.cpp')
-rw-r--r-- | src/preproc/eqn/sqrt.cpp | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/src/preproc/eqn/sqrt.cpp b/src/preproc/eqn/sqrt.cpp new file mode 100644 index 0000000..e8d7c77 --- /dev/null +++ b/src/preproc/eqn/sqrt.cpp @@ -0,0 +1,186 @@ +// -*- C++ -*- +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +This file is part of groff. + +groff is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation, either version 3 of the License, or +(at your option) any later version. + +groff is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "eqn.h" +#include "pbox.h" + + +class sqrt_box : public pointer_box { +public: + sqrt_box(box *); + int compute_metrics(int style); + void output(); + void debug_print(); + void check_tabs(int); +}; + +box *make_sqrt_box(box *pp) +{ + return new sqrt_box(pp); +} + +sqrt_box::sqrt_box(box *pp) : pointer_box(pp) +{ +} + +#define SQRT_CHAR "\\[sqrt]" +#define RADICAL_EXTENSION_CHAR "\\[sqrtex]" + +#define SQRT_CHAIN "\\[sqrt\\\\n[" INDEX_REG "]]" +#define BAR_CHAIN "\\[sqrtex\\\\n[" INDEX_REG "]]" + +int sqrt_box::compute_metrics(int style) +{ + // 11 + int r = p->compute_metrics(cramped_style(style)); + printf(".nr " TEMP_REG " \\n[" HEIGHT_FORMAT "]+\\n[" DEPTH_FORMAT + "]+%dM+(%dM/4)\n", + p->uid, p->uid, default_rule_thickness, + (style > SCRIPT_STYLE ? x_height : default_rule_thickness)); + printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid); + printf(".ds " SQRT_STRING_FORMAT " " SQRT_CHAR "\n", uid); + printf(".ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n"); + printf(".nr " SQRT_WIDTH_FORMAT + " 0\\w" DELIMITER_CHAR SQRT_CHAR DELIMITER_CHAR "\n", + uid); + printf(".if \\n[rst]-\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{", + default_rule_thickness); + + printf(".nr " INDEX_REG " 0\n" + ".de " TEMP_MACRO "\n" + ".ie c" SQRT_CHAIN " \\{" + ".ds " SQRT_STRING_FORMAT " " SQRT_CHAIN "\n" + ".ie c" BAR_CHAIN " .ds " BAR_STRING " " BAR_CHAIN "\n" + ".el .ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n" + ".nr " SQRT_WIDTH_FORMAT + " 0\\w" DELIMITER_CHAR SQRT_CHAIN DELIMITER_CHAR "\n" + ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{" + ".nr " INDEX_REG " +1\n" + "." TEMP_MACRO "\n" + ".\\}\\}\n" + ".el .nr " INDEX_REG " 0-1\n" + "..\n" + "." TEMP_MACRO "\n", + uid, uid, default_rule_thickness); + + printf(".if \\n[" INDEX_REG "]<0 \\{"); + + // Determine the maximum point size + printf(".ps 1000\n"); + printf(".nr " MAX_SIZE_REG " \\n[.ps]\n"); + printf(".ps \\n[" SIZE_FORMAT "]u\n", uid); + // We define a macro that will increase the current point size + // until we get a radical sign that's tall enough or we reach + // the maximum point size. + printf(".de " TEMP_MACRO "\n" + ".nr " SQRT_WIDTH_FORMAT + " 0\\w" DELIMITER_CHAR "\\*[" SQRT_STRING_FORMAT "]" DELIMITER_CHAR "\n" + ".if \\\\n[rst]" + "&(\\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "])" + "&(\\\\n[.ps]<\\n[" MAX_SIZE_REG "]) \\{" + ".ps +1\n" + "." TEMP_MACRO "\n" + ".\\}\n" + "..\n" + "." TEMP_MACRO "\n", + uid, uid, default_rule_thickness); + + printf(".\\}\\}\n"); + + printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid); + // set TEMP_REG to the amount by which the radical sign is too big + printf(".nr " TEMP_REG " \\n[rst]-\\n[rsb]-%dM-\\n[" TEMP_REG "]\n", + default_rule_thickness); + // If TEMP_REG is negative, the bottom of the radical sign should + // be -TEMP_REG above the bottom of p. If it's positive, the bottom + // of the radical sign should be TEMP_REG/2 below the bottom of p. + // This calculates the amount by which the baseline of the radical + // should be raised. + printf(".nr " SUP_RAISE_FORMAT " (-\\n[" TEMP_REG "]>?(-\\n[" TEMP_REG "]/2))" + "-\\n[rsb]-\\n[" DEPTH_FORMAT "]\n", uid, p->uid); + printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]" + ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n", + uid, p->uid, uid); + printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]" + ">?(-\\n[" SUP_RAISE_FORMAT "]-\\n[rsb])\n", + uid, p->uid, uid); + // Do this last, so we don't lose height and depth information on + // the radical sign. + // Remember that the width of the bar might be greater than the width of p. + + printf(".nr " TEMP_REG " " + "\\n[" WIDTH_FORMAT "]" + ">?\\w" DELIMITER_CHAR "\\*[" BAR_STRING "]" DELIMITER_CHAR "\n", + p->uid); + printf(".as " SQRT_STRING_FORMAT " " + "\\l'\\n[" TEMP_REG "]u\\&\\*[" BAR_STRING "]'\n", + uid); + printf(".nr " WIDTH_FORMAT " \\n[" TEMP_REG "]" + "+\\n[" SQRT_WIDTH_FORMAT "]\n", + uid, uid); + + if (r) + printf(".nr " MARK_REG " +\\n[" SQRT_WIDTH_FORMAT "]\n", uid); + // the top of the bar might be higher than the top of the radical sign + printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]" + ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n", + uid, p->uid, uid); + // put a bit of extra space above the bar + printf(".nr " HEIGHT_FORMAT " +%dM\n", uid, default_rule_thickness); + printf(".ps \\n[" SIZE_FORMAT "]u\n", uid); + return r; +} + +void sqrt_box::output() +{ + if (output_format == troff) { + printf("\\Z" DELIMITER_CHAR); + printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); + printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); + printf("\\*[" SQRT_STRING_FORMAT "]", uid); + printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); + printf(DELIMITER_CHAR); + + printf("\\Z" DELIMITER_CHAR); + printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u" + "+\\n[" SQRT_WIDTH_FORMAT "]u/2u'", + uid, p->uid, uid); + p->output(); + printf(DELIMITER_CHAR); + + printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); + } + else if (output_format == mathml) { + printf("<msqrt>"); + p->output(); + printf("</msqrt>"); + } +} + +void sqrt_box::debug_print() +{ + fprintf(stderr, "sqrt { "); + p->debug_print(); + fprintf(stderr, " }"); +} + +void sqrt_box::check_tabs(int level) +{ + p->check_tabs(level + 1); +} |