📄 common.cc
字号:
// -*- C++ -*-/* Copyright (C) 1989, 1990, 1991, 1992 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 underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.groff is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public License alongwith groff; see the file COPYING. If not, write to the Free SoftwareFoundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include "pic.h"#include "common.h"// output a dashed circle as a series of arcsvoid common_output::dashed_circle(const position ¢, double rad, const line_type <){ assert(lt.type == line_type::dashed); line_type slt = lt; slt.type = line_type::solid; double dash_angle = lt.dash_width/rad; int ndashes; double gap_angle; if (dash_angle >= M_PI/4.0) { if (dash_angle < M_PI/2.0) { gap_angle = M_PI/2.0 - dash_angle; ndashes = 4; } else if (dash_angle < M_PI) { gap_angle = M_PI - dash_angle; ndashes = 2; } else { circle(cent, rad, slt, -1.0); return; } } else { ndashes = 4*int(ceil(M_PI/(4.0*dash_angle))); gap_angle = (M_PI*2.0)/ndashes - dash_angle; } for (int i = 0; i < ndashes; i++) { double start_angle = i*(dash_angle+gap_angle) - dash_angle/2.0; solid_arc(cent, rad, start_angle, start_angle + dash_angle, lt); }}// output a dotted circle as a series of dotsvoid common_output::dotted_circle(const position ¢, double rad, const line_type <){ assert(lt.type == line_type::dotted); double gap_angle = lt.dash_width/rad; int ndots; if (gap_angle >= M_PI/2.0) { // always have at least 2 dots gap_angle = M_PI; ndots = 2; } else { ndots = 4*int(M_PI/(2.0*gap_angle)); gap_angle = (M_PI*2.0)/ndots; } double ang = 0.0; for (int i = 0; i < ndots; i++, ang += gap_angle) dot(cent + position(cos(ang), sin(ang))*rad, lt);}// return non-zero iff we can compute a centerint compute_arc_center(const position &start, const position ¢, const position &end, position *result){ // This finds the point along the vector from start to cent that // is equidistant between start and end. distance c = cent - start; distance e = end - start; double n = c*e; if (n == 0.0) return 0; *result = start + c*((e*e)/(2.0*n)); return 1;}// output a dashed arc as a series of arcsvoid common_output::dashed_arc(const position &start, const position ¢, const position &end, const line_type <){ assert(lt.type == line_type::dashed); position c; if (!compute_arc_center(start, cent, end, &c)) { line(start, &end, 1, lt); return; } distance start_offset = start - c; distance end_offset = end - c; double start_angle = atan2(start_offset.y, start_offset.x); double end_angle = atan2(end_offset.y, end_offset.x); double rad = hypot(c - start); double dash_angle = lt.dash_width/rad; double total_angle = end_angle - start_angle; while (total_angle < 0) total_angle += M_PI + M_PI; if (total_angle <= dash_angle*2.0) { solid_arc(cent, rad, start_angle, end_angle, lt); return; } int ndashes = int((total_angle - dash_angle)/(dash_angle*2.0) + .5); double dash_and_gap_angle = (total_angle - dash_angle)/ndashes; for (int i = 0; i <= ndashes; i++) solid_arc(cent, rad, start_angle + i*dash_and_gap_angle, start_angle + i*dash_and_gap_angle + dash_angle, lt);}// output a dotted arc as a series of dotsvoid common_output::dotted_arc(const position &start, const position ¢, const position &end, const line_type <){ assert(lt.type == line_type::dotted); position c; if (!compute_arc_center(start, cent, end, &c)) { line(start, &end, 1, lt); return; } distance start_offset = start - c; distance end_offset = end - c; double start_angle = atan2(start_offset.y, start_offset.x); double total_angle = atan2(end_offset.y, end_offset.x) - start_angle; while (total_angle < 0) total_angle += M_PI + M_PI; double rad = hypot(c - start); int ndots = int(total_angle/(lt.dash_width/rad) + .5); if (ndots == 0) dot(start, lt); else { for (int i = 0; i <= ndots; i++) { double a = start_angle + (total_angle*i)/ndots; dot(cent + position(cos(a), sin(a))*rad, lt); } }}void common_output::solid_arc(const position ¢, double rad, double start_angle, double end_angle, const line_type <){ line_type slt = lt; slt.type = line_type::solid; arc(cent + position(cos(start_angle), sin(start_angle))*rad, cent, cent + position(cos(end_angle), sin(end_angle))*rad, slt);}void common_output::rounded_box(const position ¢, const distance &dim, double rad, const line_type <, double fill){ if (fill >= 0.0) filled_rounded_box(cent, dim, rad, fill); switch (lt.type) { case line_type::invisible: break; case line_type::dashed: dashed_rounded_box(cent, dim, rad, lt); break; case line_type::dotted: dotted_rounded_box(cent, dim, rad, lt); break; case line_type::solid: solid_rounded_box(cent, dim, rad, lt); break; default: assert(0); }}void common_output::dashed_rounded_box(const position ¢, const distance &dim, double rad, const line_type <){ line_type slt = lt; slt.type = line_type::solid; double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad; int n_hor_dashes = int(hor_length/(lt.dash_width*2.0) + .5); double hor_gap_width = (n_hor_dashes != 0 ? hor_length/n_hor_dashes - lt.dash_width : 0.0); double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad; int n_vert_dashes = int(vert_length/(lt.dash_width*2.0) + .5); double vert_gap_width = (n_vert_dashes != 0 ? vert_length/n_vert_dashes - lt.dash_width : 0.0); // Note that each corner arc has to be split into two for dashing, // because one part is dashed using vert_gap_width, and the other // using hor_gap_width. double offset = lt.dash_width/2.0; dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, -M_PI/4.0, 0, slt, lt.dash_width, vert_gap_width, &offset); dash_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad), cent + position(dim.x/2.0, dim.y/2.0 - rad), slt, lt.dash_width, vert_gap_width, &offset); dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, 0, M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset); offset = lt.dash_width/2.0; dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, M_PI/4.0, M_PI/2, slt, lt.dash_width, hor_gap_width, &offset); dash_line(cent + position(dim.x/2.0 - rad, dim.y/2.0), cent + position(-dim.x/2.0 + rad, dim.y/2.0), slt, lt.dash_width, hor_gap_width, &offset); dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, M_PI/2, 3*M_PI/4.0, slt, lt.dash_width, hor_gap_width, &offset); offset = lt.dash_width/2.0; dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, 3.0*M_PI/4.0, M_PI, slt, lt.dash_width, vert_gap_width, &offset); dash_line(cent + position(-dim.x/2.0, dim.y/2.0 - rad), cent + position(-dim.x/2.0, -dim.y/2.0 + rad), slt, lt.dash_width, vert_gap_width, &offset); dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, M_PI, 5.0*M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset); offset = lt.dash_width/2.0; dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, 5*M_PI/4.0, 3*M_PI/2.0, slt, lt.dash_width, hor_gap_width, &offset); dash_line(cent + position(-dim.x/2.0 + rad, -dim.y/2.0), cent + position(dim.x/2.0 - rad, -dim.y/2.0), slt, lt.dash_width, hor_gap_width, &offset); dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, 3*M_PI/2, 7*M_PI/4, slt, lt.dash_width, hor_gap_width, &offset);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -