Commit | Line | Data |
---|---|---|
659d7144 WJ |
1 | /* Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
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 */ | |
32 | int | |
33 | gs_setlinewidth(gs_state *pgs, floatp width) | |
34 | { pgs->line_params->width = width / 2; | |
35 | return 0; | |
36 | } | |
37 | ||
38 | /* currentlinewidth */ | |
39 | float | |
40 | gs_currentlinewidth(const gs_state *pgs) | |
41 | { return (float)(pgs->line_params->width * 2); | |
42 | } | |
43 | ||
44 | /* setlinecap */ | |
45 | int | |
46 | gs_setlinecap(gs_state *pgs, gs_line_cap cap) | |
47 | { pgs->line_params->cap = cap; | |
48 | return 0; | |
49 | } | |
50 | ||
51 | /* currentlinecap */ | |
52 | gs_line_cap | |
53 | gs_currentlinecap(const gs_state *pgs) | |
54 | { return pgs->line_params->cap; | |
55 | } | |
56 | ||
57 | /* setlinejoin */ | |
58 | int | |
59 | gs_setlinejoin(gs_state *pgs, gs_line_join join) | |
60 | { pgs->line_params->join = join; | |
61 | return 0; | |
62 | } | |
63 | ||
64 | /* currentlinejoin */ | |
65 | gs_line_join | |
66 | gs_currentlinejoin(const gs_state *pgs) | |
67 | { return pgs->line_params->join; | |
68 | } | |
69 | ||
70 | /* setmiterlimit */ | |
71 | int | |
72 | gs_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 */ | |
94 | float | |
95 | gs_currentmiterlimit(const gs_state *pgs) | |
96 | { return pgs->line_params->miter_limit; | |
97 | } | |
98 | ||
99 | /* setdash */ | |
100 | int | |
101 | gs_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 */ | |
144 | uint | |
145 | gs_currentdash_length(const gs_state *pgs) | |
146 | { return pgs->line_params->dash.pattern_size; | |
147 | } | |
148 | int | |
149 | gs_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 | } | |
153 | float | |
154 | gs_currentdash_offset(const gs_state *pgs) | |
155 | { return pgs->line_params->dash.offset; | |
156 | } |