PageRenderTime 45ms CodeModel.GetById 9ms app.highlight 30ms RepoModel.GetById 2ms app.codeStats 0ms

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

https://bitbucket.org/freebsd/freebsd-head/
C++ | 197 lines | 144 code | 19 blank | 34 comment | 11 complexity | a54d8b379384aabf99abe13f0cfe7db8 MD5 | raw file
  1// -*- C++ -*-
  2/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
  3   Free Software Foundation, Inc.
  4     Written by James Clark (jjc@jclark.com)
  5
  6This file is part of groff.
  7
  8groff is free software; you can redistribute it and/or modify it under
  9the terms of the GNU General Public License as published by the Free
 10Software Foundation; either version 2, or (at your option) any later
 11version.
 12
 13groff is distributed in the hope that it will be useful, but WITHOUT ANY
 14WARRANTY; without even the implied warranty of MERCHANTABILITY or
 15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 16for more details.
 17
 18You should have received a copy of the GNU General Public License along
 19with groff; see the file COPYING.  If not, write to the Free Software
 20Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
 21
 22#include "eqn.h"
 23#include "pbox.h"
 24
 25class over_box : public box {
 26private:
 27  int reduce_size;
 28  box *num;
 29  box *den;
 30public:
 31  over_box(int small, box *, box *);
 32  ~over_box();
 33  void debug_print();
 34  int compute_metrics(int);
 35  void output();
 36  void check_tabs(int);
 37};
 38
 39box *make_over_box(box *pp, box *qq)
 40{
 41  return new over_box(0, pp, qq);
 42}
 43
 44box *make_small_over_box(box *pp, box *qq)
 45{
 46  return new over_box(1, pp, qq);
 47}
 48
 49over_box::over_box(int is_small, box *pp, box *qq)
 50: reduce_size(is_small), num(pp), den(qq)
 51{
 52  spacing_type = INNER_TYPE;
 53}
 54
 55over_box::~over_box()
 56{
 57  delete num;
 58  delete den;
 59}
 60
 61int over_box::compute_metrics(int style)
 62{
 63  if (reduce_size) {
 64    style = script_style(style);
 65    printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
 66    set_script_size();
 67    printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
 68  }
 69  int mark_uid = 0;
 70  int res = num->compute_metrics(style);
 71  if (res)
 72    mark_uid = num->uid;
 73  int r = den->compute_metrics(cramped_style(style));
 74  if (r && res)
 75    error("multiple marks and lineups");
 76  else {
 77    mark_uid = den->uid;
 78    res = r;
 79  }
 80  if (reduce_size)
 81    printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
 82  printf(".nr " WIDTH_FORMAT " (\\n[" WIDTH_FORMAT "]>?\\n[" WIDTH_FORMAT "]", 
 83	 uid, num->uid, den->uid);
 84  // allow for \(ru being wider than both the numerator and denominator
 85  if (!draw_flag)
 86    fputs(">?\\w" DELIMITER_CHAR "\\(ru" DELIMITER_CHAR, stdout);
 87  printf(")+%dM\n", null_delimiter_space*2 + over_hang*2);
 88  // 15b
 89  printf(".nr " SUP_RAISE_FORMAT " %dM\n",
 90	 uid, (reduce_size ? num2 : num1));
 91  printf(".nr " SUB_LOWER_FORMAT " %dM\n",
 92	 uid, (reduce_size ? denom2 : denom1));
 93
 94  // 15d
 95  printf(".nr " SUP_RAISE_FORMAT " +(\\n[" DEPTH_FORMAT
 96	 "]-\\n[" SUP_RAISE_FORMAT "]+%dM+(%dM/2)+%dM)>?0\n",
 97	 uid, num->uid, uid, axis_height, default_rule_thickness,
 98	 default_rule_thickness*(reduce_size ? 1 : 3));
 99  printf(".nr " SUB_LOWER_FORMAT " +(\\n[" HEIGHT_FORMAT
100	 "]-\\n[" SUB_LOWER_FORMAT "]-%dM+(%dM/2)+%dM)>?0\n",
101	 uid, den->uid, uid, axis_height, default_rule_thickness,
102	 default_rule_thickness*(reduce_size ? 1 : 3));
103
104
105  printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
106	 HEIGHT_FORMAT "]\n",
107	 uid, uid, num->uid);
108  printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n["
109	 DEPTH_FORMAT "]\n",
110	 uid, uid, den->uid);
111  if (res)
112    printf(".nr " MARK_REG " +(\\n[" WIDTH_FORMAT "]-\\n["
113	   WIDTH_FORMAT "]/2)\n", uid, mark_uid);
114  return res;
115}
116
117#define USE_Z
118
119void over_box::output()
120{
121  if (reduce_size)
122    printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
123#ifdef USE_Z
124  printf("\\Z" DELIMITER_CHAR);
125#endif
126  // move up to the numerator baseline
127  printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
128  // move across so that it's centered
129  printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
130	 uid, num->uid);
131
132  // print the numerator
133  num->output();
134
135#ifdef USE_Z
136  printf(DELIMITER_CHAR);
137#else
138  // back again
139  printf("\\h'-\\n[" WIDTH_FORMAT "]u'", num->uid);
140  printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
141	 uid, num->uid);
142  // down again
143  printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
144#endif
145#ifdef USE_Z
146  printf("\\Z" DELIMITER_CHAR);
147#endif
148  // move down to the denominator baseline
149  printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
150
151  // move across so that it's centered
152  printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
153	 uid, den->uid);
154
155  // print the the denominator
156  den->output();
157
158#ifdef USE_Z
159  printf(DELIMITER_CHAR);
160#else
161  // back again
162  printf("\\h'-\\n[" WIDTH_FORMAT "]u'", den->uid);
163  printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
164	 uid, den->uid);
165  // up again
166  printf("\\v'-\\n[" SUB_LOWER_FORMAT "]u'", uid);
167#endif
168  if (reduce_size)
169    printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
170  // draw the line
171  printf("\\h'%dM'", null_delimiter_space);
172  printf("\\v'-%dM'", axis_height);
173  fputs(draw_flag ? "\\D'l" : "\\l'", stdout);
174  printf("\\n[" WIDTH_FORMAT "]u-%dM",
175	 uid, 2*null_delimiter_space);
176  fputs(draw_flag ? " 0'" : "\\&\\(ru'", stdout);
177  printf("\\v'%dM'", axis_height);
178  printf("\\h'%dM'", null_delimiter_space);
179}
180
181void over_box::debug_print()
182{
183  fprintf(stderr, "{ ");
184  num->debug_print();
185  if (reduce_size)
186    fprintf(stderr, " } smallover { ");
187  else
188    fprintf(stderr, " } over { ");
189  den->debug_print();
190  fprintf(stderr, " }");
191}
192
193void over_box::check_tabs(int level)
194{
195  num->check_tabs(level + 1);
196  den->check_tabs(level + 1);
197}