386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / gsline.c
CommitLineData
659d7144
WJ
1/* Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved.
2 Distributed by Free Software Foundation, Inc.
3
4This file is part of Ghostscript.
5
6Ghostscript is distributed in the hope that it will be useful, but
7WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
8to anyone for the consequences of using it or for whether it serves any
9particular purpose or works at all, unless he says so in writing. Refer
10to the Ghostscript General Public License for full details.
11
12Everyone is granted permission to copy, modify and redistribute
13Ghostscript, but only under the conditions described in the Ghostscript
14General Public License. A copy of this license is supposed to have been
15given to you along with Ghostscript so you can know your rights and
16responsibilities. It should be in a file named COPYING. Among other
17things, the copyright notice and this notice must be preserved on all
18copies. */
19
20/* gsline.c */
21/* Line parameter operators for GhostScript library */
22#include "math_.h"
23#include "memory_.h"
24#include "gx.h"
25#include "gserrors.h"
26#include "gxfixed.h" /* ditto */
27#include "gxmatrix.h" /* for gzstate */
28#include "gzstate.h"
29#include "gzline.h"
30
31/* setlinewidth */
32int
33gs_setlinewidth(gs_state *pgs, floatp width)
34{ pgs->line_params->width = width / 2;
35 return 0;
36}
37
38/* currentlinewidth */
39float
40gs_currentlinewidth(const gs_state *pgs)
41{ return (float)(pgs->line_params->width * 2);
42}
43
44/* setlinecap */
45int
46gs_setlinecap(gs_state *pgs, gs_line_cap cap)
47{ pgs->line_params->cap = cap;
48 return 0;
49}
50
51/* currentlinecap */
52gs_line_cap
53gs_currentlinecap(const gs_state *pgs)
54{ return pgs->line_params->cap;
55}
56
57/* setlinejoin */
58int
59gs_setlinejoin(gs_state *pgs, gs_line_join join)
60{ pgs->line_params->join = join;
61 return 0;
62}
63
64/* currentlinejoin */
65gs_line_join
66gs_currentlinejoin(const gs_state *pgs)
67{ return pgs->line_params->join;
68}
69
70/* setmiterlimit */
71int
72gs_setmiterlimit(gs_state *pgs, floatp limit)
73{ if ( limit < 1.0 ) return_error(gs_error_rangecheck);
74 pgs->line_params->miter_limit = limit;
75 /* The supplied miter limit is an upper bound on */
76 /* 1/sin(phi/2). We convert this to a lower bound on */
77 /* tan(phi). Note that if phi > pi/2, this is negative. */
78 /* We use the half-angle and angle-sum formulas here */
79 /* to avoid the trig functions.... */
80 { double limit_sq = limit * limit;
81 /* We need a special check for phi/2 close to pi/4. */
82 /* Some C compilers can't handle the following as a */
83 /* conditional expression.... */
84 if ( limit_sq < 2.0001 && limit_sq > 1.9999 )
85 pgs->line_params->miter_check = 1.0e6;
86 else
87 pgs->line_params->miter_check =
88 sqrt(limit_sq - 1) * 2 / (limit_sq - 2);
89 }
90 return 0;
91}
92
93/* currentmiterlimit */
94float
95gs_currentmiterlimit(const gs_state *pgs)
96{ return pgs->line_params->miter_limit;
97}
98
99/* setdash */
100int
101gs_setdash(gs_state *pgs, const float *pattern, uint length, floatp offset)
102{ uint n = length;
103 const float *dfrom = pattern;
104 char ink = 1;
105 int index = 0;
106 float pattern_length = 0.0;
107 float dist_left;
108 dash_params *dash = &pgs->line_params->dash;
109 float *ppat;
110 /* Check the dash pattern */
111 while ( n-- )
112 { float elt = *dfrom++;
113 if ( elt < 0 ) return_error(gs_error_rangecheck);
114 pattern_length += elt;
115 }
116 if ( length == 0 ) /* empty pattern */
117 { dist_left = 0.0;
118 ppat = 0;
119 }
120 else
121 { if ( pattern_length == 0 )
122 return_error(gs_error_rangecheck);
123 /* Compute the initial index, ink_on, and distance left */
124 /* in the pattern, according to the offset. */
125#define f_mod(a, b) ((a) - floor((a) / (b)) * (b))
126 dist_left = f_mod(offset, pattern_length);
127 while ( (dist_left -= pattern[index]) >= 0 )
128 ink = !ink, index++;
129 ppat = (float *)gs_malloc(length, sizeof(float),
130 "dash pattern");
131 if ( ppat == 0 ) return_error(gs_error_VMerror);
132 memcpy(ppat, pattern, length * sizeof(float));
133 }
134 dash->pattern = ppat;
135 dash->pattern_size = length;
136 dash->offset = offset;
137 dash->init_ink_on = ink;
138 dash->init_index = index;
139 dash->init_dist_left = -dist_left;
140 return 0;
141}
142
143/* currentdash */
144uint
145gs_currentdash_length(const gs_state *pgs)
146{ return pgs->line_params->dash.pattern_size;
147}
148int
149gs_currentdash_pattern(const gs_state *pgs, float *pattern)
150{ memcpy(pattern, pgs->line_params->dash.pattern, pgs->line_params->dash.pattern_size * sizeof(float));
151 return 0;
152}
153float
154gs_currentdash_offset(const gs_state *pgs)
155{ return pgs->line_params->dash.offset;
156}