tioga 1.6 → 1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Tioga_README +35 -10
- data/split/Dvector/dvector.c +264 -22
- data/split/Dvector/lib/Dvector_extras.rb +30 -2
- data/split/Flate/extconf.rb +1 -1
- data/split/Function/function.c +112 -2
- data/split/Tioga/figures.c +76 -77
- data/split/Tioga/figures.h +375 -490
- data/split/Tioga/generic.c +254 -0
- data/split/Tioga/generic.h +236 -0
- data/split/Tioga/init.c +434 -320
- data/split/Tioga/lib/Creating_Paths.rb +11 -1
- data/split/Tioga/lib/FigMkr.rb +263 -65
- data/split/Tioga/lib/Legends.rb +4 -2
- data/split/Tioga/lib/Markers.rb +3 -2
- data/split/Tioga/lib/Special_Paths.rb +22 -23
- data/split/Tioga/lib/TeX_Text.rb +79 -1
- data/split/Tioga/lib/TexPreamble.rb +14 -0
- data/split/Tioga/lib/Utils.rb +5 -1
- data/split/Tioga/pdfs.h +7 -45
- data/split/Tioga/{axes.c → shared/axes.c} +210 -197
- data/split/Tioga/{makers.c → shared/makers.c} +442 -211
- data/split/Tioga/{pdf_font_dicts.c → shared/pdf_font_dicts.c} +0 -0
- data/split/Tioga/shared/pdfcolor.c +628 -0
- data/split/Tioga/shared/pdfcoords.c +443 -0
- data/split/Tioga/{pdffile.c → shared/pdffile.c} +56 -52
- data/split/Tioga/{pdfimage.c → shared/pdfimage.c} +103 -211
- data/split/Tioga/shared/pdfpath.c +766 -0
- data/split/Tioga/{pdftext.c → shared/pdftext.c} +121 -99
- data/split/Tioga/shared/texout.c +524 -0
- data/split/Tioga/wrappers.c +489 -0
- data/split/Tioga/wrappers.h +259 -0
- data/split/extconf.rb +4 -0
- data/split/mkmf2.rb +12 -1
- data/tests/benchmark_dvector_reads.rb +112 -0
- data/tests/tc_Dvector.rb +35 -3
- data/tests/tc_Function.rb +32 -0
- metadata +65 -52
- data/split/Tioga/pdfcolor.c +0 -486
- data/split/Tioga/pdfcoords.c +0 -523
- data/split/Tioga/pdfpath.c +0 -913
- data/split/Tioga/texout.c +0 -380
data/split/Tioga/pdfpath.c
DELETED
@@ -1,913 +0,0 @@
|
|
1
|
-
/* pdfpath.c */
|
2
|
-
/*
|
3
|
-
Copyright (C) 2005 Bill Paxton
|
4
|
-
|
5
|
-
This file is part of Tioga.
|
6
|
-
|
7
|
-
Tioga is free software; you can redistribute it and/or modify
|
8
|
-
it under the terms of the GNU General Library Public License as published
|
9
|
-
by the Free Software Foundation; either version 2 of the License, or
|
10
|
-
(at your option) any later version.
|
11
|
-
|
12
|
-
Tioga is distributed in the hope that it will be useful,
|
13
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
-
GNU Library General Public License for more details.
|
16
|
-
|
17
|
-
You should have received a copy of the GNU Library General Public License
|
18
|
-
along with Tioga; if not, write to the Free Software
|
19
|
-
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
20
|
-
*/
|
21
|
-
|
22
|
-
#include "figures.h"
|
23
|
-
#include "pdfs.h"
|
24
|
-
|
25
|
-
bool have_current_point, constructing_path, writing_file;
|
26
|
-
double bbox_llx, bbox_lly, bbox_urx, bbox_ury;
|
27
|
-
|
28
|
-
/* emits a warning on nonok numbers if croak_on_nonok_numbers is true */
|
29
|
-
static void croak_on_nonok(FM *p, const char * function)
|
30
|
-
{
|
31
|
-
if(p->croak_on_nonok_numbers)
|
32
|
-
rb_warn("Illegal coordinates in function %s, element suppressed",
|
33
|
-
function);
|
34
|
-
}
|
35
|
-
|
36
|
-
/* small macro to check if a number is ok to be output */
|
37
|
-
|
38
|
-
#define CROAK_ON_NONOK(p) croak_on_nonok(p, __FUNCTION__)
|
39
|
-
#define ARE_OK_NUMBERS(x,y) if(! is_okay_number(x) || ! is_okay_number(y)) {\
|
40
|
-
CROAK_ON_NONOK(p); return;}
|
41
|
-
|
42
|
-
|
43
|
-
/* PDF graphics */
|
44
|
-
|
45
|
-
/* graphics attributes */
|
46
|
-
|
47
|
-
void Unpack_RGB(VALUE rgb, double *rp, double *gp, double *bp)
|
48
|
-
{
|
49
|
-
if (rgb == Qnil) { *rp = *gp = *bp = 0.0; return; }
|
50
|
-
rgb = rb_Array(rgb);
|
51
|
-
if (RARRAY(rgb)->len != 3) rb_raise(rb_eArgError, "Sorry: invalid rgb array for setting color: must have 3 entries");
|
52
|
-
VALUE entry = rb_ary_entry(rgb, 0);
|
53
|
-
entry = rb_Float(entry);
|
54
|
-
double r = NUM2DBL(entry);
|
55
|
-
entry = rb_ary_entry(rgb, 1);
|
56
|
-
entry = rb_Float(entry);
|
57
|
-
double g = NUM2DBL(entry);
|
58
|
-
entry = rb_ary_entry(rgb, 2);
|
59
|
-
entry = rb_Float(entry);
|
60
|
-
double b = NUM2DBL(entry);
|
61
|
-
if (r < 0.0 || r > 1.0) rb_raise(rb_eArgError, "Sorry: invalid red (%g) for color: must be between 0 and 1", r);
|
62
|
-
if (g < 0.0 || g > 1.0) rb_raise(rb_eArgError, "Sorry: invalid green (%g) for color: must be between 0 and 1", g);
|
63
|
-
if (b < 0.0 || b > 1.0) rb_raise(rb_eArgError, "Sorry: invalid blue (%g) for color: must be between 0 and 1", b);
|
64
|
-
*rp = r; *gp = g; *bp = b;
|
65
|
-
}
|
66
|
-
|
67
|
-
void c_stroke_color_set(FM *p, double r, double g, double b)
|
68
|
-
{
|
69
|
-
if (writing_file) fprintf(TF, "%0.3f %0.3f %0.3f RG\n", r, g, b);
|
70
|
-
}
|
71
|
-
|
72
|
-
VALUE FM_stroke_color_set(VALUE fmkr, VALUE value) // value is array of [r, g, b] intensities from 0 to 1
|
73
|
-
{ // r g b RG
|
74
|
-
FM *p = Get_FM(fmkr);
|
75
|
-
double r, g, b;
|
76
|
-
Unpack_RGB(value, &r, &g, &b);
|
77
|
-
c_stroke_color_set(p, r, g, b);
|
78
|
-
p->stroke_color = value;
|
79
|
-
return value;
|
80
|
-
}
|
81
|
-
|
82
|
-
VALUE FM_fill_color_set(VALUE fmkr, VALUE value) // value is array of [r, g, b] intensities from 0 to 1
|
83
|
-
{ // r g b rg
|
84
|
-
FM *p = Get_FM(fmkr);
|
85
|
-
double r, g, b;
|
86
|
-
Unpack_RGB(value, &r, &g, &b);
|
87
|
-
if (writing_file) fprintf(TF, "%0.3f %0.3f %0.3f rg\n", r, g, b);
|
88
|
-
p->fill_color = value;
|
89
|
-
return value;
|
90
|
-
}
|
91
|
-
|
92
|
-
void c_line_width_set(FM *p, double line_width)
|
93
|
-
{
|
94
|
-
if (line_width < 0.0) rb_raise(rb_eArgError, "Sorry: invalid line width (%g points): must be positive", line_width);
|
95
|
-
if (line_width > 1e3) rb_raise(rb_eArgError, "Sorry: too large line width (%g points)", line_width);
|
96
|
-
if (writing_file) fprintf(TF, "%0.3f w\n", line_width * ENLARGE * p->default_line_scale);
|
97
|
-
p->line_width = line_width;
|
98
|
-
}
|
99
|
-
|
100
|
-
VALUE FM_line_width_set(VALUE fmkr, VALUE value) // value is thickness in points
|
101
|
-
{ // w
|
102
|
-
FM *p = Get_FM(fmkr);
|
103
|
-
value = rb_Float(value);
|
104
|
-
c_line_width_set(p, NUM2DBL(value));
|
105
|
-
return value;
|
106
|
-
}
|
107
|
-
|
108
|
-
void c_line_scale_set(FM *p, double new_scale)
|
109
|
-
{
|
110
|
-
if (new_scale <= 0) rb_raise(rb_eArgError, "Sorry: line scale must be positive");
|
111
|
-
p->default_line_scale = new_scale;
|
112
|
-
c_line_width_set(p, p->line_width);
|
113
|
-
}
|
114
|
-
|
115
|
-
VALUE FM_rescale_lines(VALUE fmkr, VALUE scaling_factor)
|
116
|
-
{
|
117
|
-
FM *p = Get_FM(fmkr);
|
118
|
-
scaling_factor = rb_Float(scaling_factor);
|
119
|
-
c_line_scale_set(p, NUM2DBL(scaling_factor) * p->default_line_scale);
|
120
|
-
return fmkr;
|
121
|
-
}
|
122
|
-
|
123
|
-
void c_line_cap_set(FM *p, int line_cap)
|
124
|
-
{
|
125
|
-
if (line_cap < 0 || line_cap > 3) rb_raise(rb_eArgError, "Sorry: invalid arg for setting line_cap (%i)", line_cap);
|
126
|
-
if (writing_file) fprintf(TF, "%d J\n", line_cap);
|
127
|
-
p->line_cap = line_cap;
|
128
|
-
}
|
129
|
-
|
130
|
-
VALUE FM_line_cap_set(VALUE fmkr, VALUE value)
|
131
|
-
{ // J
|
132
|
-
FM *p = Get_FM(fmkr);
|
133
|
-
value = rb_Integer(value);
|
134
|
-
c_line_cap_set(p, NUM2INT(value));
|
135
|
-
return value;
|
136
|
-
}
|
137
|
-
|
138
|
-
void c_line_join_set(FM *p, int line_join)
|
139
|
-
{
|
140
|
-
if (line_join < 0 || line_join > 3) rb_raise(rb_eArgError, "Sorry: invalid arg for setting line_join (%i)", line_join);
|
141
|
-
if (writing_file) fprintf(TF, "%d j\n", line_join);
|
142
|
-
p->line_join = line_join;
|
143
|
-
}
|
144
|
-
|
145
|
-
VALUE FM_line_join_set(VALUE fmkr, VALUE value)
|
146
|
-
{ // j
|
147
|
-
FM *p = Get_FM(fmkr);
|
148
|
-
value = rb_Integer(value);
|
149
|
-
c_line_join_set(p, NUM2INT(value));
|
150
|
-
return value;
|
151
|
-
}
|
152
|
-
|
153
|
-
void c_miter_limit_set(FM *p, double miter_limit)
|
154
|
-
{
|
155
|
-
if (miter_limit < 0.0)
|
156
|
-
rb_raise(rb_eArgError,
|
157
|
-
"Sorry: invalid miter limit (%g): must be positive ratio for max miter length to line width", miter_limit);
|
158
|
-
if (writing_file) fprintf(TF, "%0.3f M\n", miter_limit);
|
159
|
-
p->miter_limit = miter_limit;
|
160
|
-
}
|
161
|
-
|
162
|
-
VALUE FM_miter_limit_set(VALUE fmkr, VALUE value) // value is max ratio of miter length to line width
|
163
|
-
{ // M
|
164
|
-
FM *p = Get_FM(fmkr);
|
165
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must not be constructing a path when change miter limit");
|
166
|
-
value = rb_Float(value);
|
167
|
-
c_miter_limit_set(p, NUM2DBL(value));
|
168
|
-
return value;
|
169
|
-
}
|
170
|
-
|
171
|
-
VALUE FM_line_type_set(VALUE fmkr, VALUE line_type)
|
172
|
-
{ // array phase d (distances given in points)
|
173
|
-
FM *p = Get_FM(fmkr);
|
174
|
-
double sz;
|
175
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must not be constructing a path when change line_type");
|
176
|
-
if (line_type == Qnil) {
|
177
|
-
fprintf(TF, "[] 0 d\n");
|
178
|
-
} else {
|
179
|
-
line_type = rb_Array(line_type);
|
180
|
-
if (writing_file) {
|
181
|
-
if (RARRAY(line_type)->len != 2)
|
182
|
-
rb_raise(rb_eArgError, "Sorry: invalid line_type. Must be [ [dash pattern] dash phase ]");
|
183
|
-
VALUE dashArray = rb_ary_entry(line_type, 0), dashPhase = rb_ary_entry(line_type, 1);
|
184
|
-
fprintf(TF, "[ ");
|
185
|
-
if (dashArray != Qnil) {
|
186
|
-
dashArray = rb_Array(dashArray);
|
187
|
-
long i, len = RARRAY(dashArray)->len;
|
188
|
-
for (i=0; i < len; i++) {
|
189
|
-
VALUE entry = rb_ary_entry(dashArray, i);
|
190
|
-
entry = rb_Float(entry);
|
191
|
-
sz = NUM2DBL(entry);
|
192
|
-
if (sz < 0.0) rb_raise(rb_eArgError, "Sorry: invalid dash array entry (%g): must be positive", sz);
|
193
|
-
fprintf(TF, "%0.3f ", sz * ENLARGE);
|
194
|
-
}
|
195
|
-
}
|
196
|
-
dashPhase = rb_Float(dashPhase);
|
197
|
-
sz = NUM2DBL(dashPhase);
|
198
|
-
if (sz < 0.0) rb_raise(rb_eArgError, "Sorry: invalid dash phase (%g): must be positive", sz);
|
199
|
-
fprintf(TF, "] %0.3f d\n", sz * ENLARGE);
|
200
|
-
}
|
201
|
-
}
|
202
|
-
p->line_type = line_type;
|
203
|
-
return fmkr;
|
204
|
-
}
|
205
|
-
|
206
|
-
|
207
|
-
/* Path construction operators */
|
208
|
-
|
209
|
-
/* all locations and vectors are in figure coordinates */
|
210
|
-
|
211
|
-
long c_round_dev(FM *p, double v) { // make sure that we don't get too far out or can overflow!
|
212
|
-
if (v > MAX_DEV_COORD_ALLOWED) {
|
213
|
-
//if (p->debug_verbosity_level > 0) printf("c_round_dev clipping %g\n", v);
|
214
|
-
return iMAX_DEV_COORD_ALLOWED;
|
215
|
-
}
|
216
|
-
if (v < -MAX_DEV_COORD_ALLOWED) {
|
217
|
-
//if (p->debug_verbosity_level > 0) printf("c_round_dev clipping %g\n", v);
|
218
|
-
return -iMAX_DEV_COORD_ALLOWED;
|
219
|
-
}
|
220
|
-
return ROUND(v);
|
221
|
-
}
|
222
|
-
|
223
|
-
void update_bbox(FM *p, double x, double y)
|
224
|
-
{
|
225
|
-
if (x >= p->clip_left && x < bbox_llx) bbox_llx = x;
|
226
|
-
if (y >= p->clip_bottom && y < bbox_lly) bbox_lly = y;
|
227
|
-
if (x <= p->clip_right && x > bbox_urx) bbox_urx = x;
|
228
|
-
if (y <= p->clip_top && y > bbox_ury) bbox_ury = y;
|
229
|
-
}
|
230
|
-
|
231
|
-
VALUE FM_update_bbox(VALUE fmkr, VALUE x, VALUE y)
|
232
|
-
{
|
233
|
-
FM *p = Get_FM(fmkr);
|
234
|
-
x = rb_Float(x);
|
235
|
-
y = rb_Float(y);
|
236
|
-
update_bbox(p, convert_figure_to_output_x(p,NUM2DBL(x)), convert_figure_to_output_y(p,NUM2DBL(y)));
|
237
|
-
return fmkr;
|
238
|
-
}
|
239
|
-
|
240
|
-
|
241
|
-
VALUE FM_bbox_left(VALUE fmkr)
|
242
|
-
{
|
243
|
-
return rb_float_new(bbox_llx);
|
244
|
-
}
|
245
|
-
|
246
|
-
VALUE FM_bbox_right(VALUE fmkr)
|
247
|
-
{
|
248
|
-
return rb_float_new(bbox_urx);
|
249
|
-
}
|
250
|
-
|
251
|
-
VALUE FM_bbox_top(VALUE fmkr)
|
252
|
-
{
|
253
|
-
return rb_float_new(bbox_ury);
|
254
|
-
}
|
255
|
-
|
256
|
-
VALUE FM_bbox_bottom(VALUE fmkr)
|
257
|
-
{
|
258
|
-
return rb_float_new(bbox_lly);
|
259
|
-
}
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
void c_moveto(FM *p, double x, double y)
|
264
|
-
{
|
265
|
-
ARE_OK_NUMBERS(x,y);
|
266
|
-
if (writing_file) fprintf(TF, "%ld %ld m\n", c_round_dev(p,x), c_round_dev(p,y));
|
267
|
-
update_bbox(p, x, y);
|
268
|
-
have_current_point = constructing_path = true;
|
269
|
-
}
|
270
|
-
|
271
|
-
VALUE FM_move_to_point(VALUE fmkr, VALUE x, VALUE y)
|
272
|
-
{
|
273
|
-
FM *p = Get_FM(fmkr);
|
274
|
-
x = rb_Float(x);
|
275
|
-
y = rb_Float(y);
|
276
|
-
double dev_x = convert_figure_to_output_x(p,NUM2DBL(x)), dev_y = convert_figure_to_output_y(p,NUM2DBL(y));
|
277
|
-
c_moveto(p, dev_x, dev_y);
|
278
|
-
return fmkr;
|
279
|
-
}
|
280
|
-
|
281
|
-
void c_lineto(FM *p, double x, double y)
|
282
|
-
{
|
283
|
-
ARE_OK_NUMBERS(x,y);
|
284
|
-
if (!constructing_path) rb_raise(rb_eArgError, "Sorry: must start path with moveto before call lineto");
|
285
|
-
if (writing_file) fprintf(TF, "%ld %ld l\n", c_round_dev(p,x), c_round_dev(p,y));
|
286
|
-
update_bbox(p, x, y);
|
287
|
-
}
|
288
|
-
|
289
|
-
VALUE FM_append_point_to_path(VALUE fmkr, VALUE x, VALUE y)
|
290
|
-
{
|
291
|
-
FM *p = Get_FM(fmkr);
|
292
|
-
x = rb_Float(x);
|
293
|
-
y = rb_Float(y);
|
294
|
-
double dev_x = convert_figure_to_output_x(p,NUM2DBL(x)), dev_y = convert_figure_to_output_y(p,NUM2DBL(y));
|
295
|
-
c_lineto(p, dev_x, dev_y);
|
296
|
-
return fmkr;
|
297
|
-
}
|
298
|
-
|
299
|
-
void c_curveto(FM *p, double x1, double y1, double x2, double y2, double x3, double y3)
|
300
|
-
{
|
301
|
-
ARE_OK_NUMBERS(x1,y1);
|
302
|
-
ARE_OK_NUMBERS(x2,y2);
|
303
|
-
ARE_OK_NUMBERS(x3,y3);
|
304
|
-
if (!constructing_path) rb_raise(rb_eArgError, "Sorry: must start path with moveto before call curveto");
|
305
|
-
if (writing_file) fprintf(TF, "%ld %ld %ld %ld %ld %ld c\n",
|
306
|
-
c_round_dev(p,x1), c_round_dev(p,y1), c_round_dev(p,x2), c_round_dev(p,y2), c_round_dev(p,x3), c_round_dev(p,y3));
|
307
|
-
update_bbox(p, x1, y1);
|
308
|
-
update_bbox(p, x2, y2);
|
309
|
-
update_bbox(p, x3, y3);
|
310
|
-
}
|
311
|
-
|
312
|
-
VALUE FM_append_curve_to_path(VALUE fmkr, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE x3, VALUE y3)
|
313
|
-
{
|
314
|
-
FM *p = Get_FM(fmkr);
|
315
|
-
x1 = rb_Float(x1);
|
316
|
-
y1 = rb_Float(y1);
|
317
|
-
x2 = rb_Float(x2);
|
318
|
-
y2 = rb_Float(y2);
|
319
|
-
x3 = rb_Float(x3);
|
320
|
-
y3 = rb_Float(y3);
|
321
|
-
double dev_x1 = convert_figure_to_output_x(p,NUM2DBL(x1)), dev_y1 = convert_figure_to_output_y(p,NUM2DBL(y1));
|
322
|
-
double dev_x2 = convert_figure_to_output_x(p,NUM2DBL(x2)), dev_y2 = convert_figure_to_output_y(p,NUM2DBL(y2));
|
323
|
-
double dev_x3 = convert_figure_to_output_x(p,NUM2DBL(x3)), dev_y3 = convert_figure_to_output_y(p,NUM2DBL(y3));
|
324
|
-
c_curveto(p, dev_x1, dev_y1, dev_x2, dev_y2, dev_x3, dev_y3);
|
325
|
-
return fmkr;
|
326
|
-
}
|
327
|
-
|
328
|
-
void c_closepath(FM *p)
|
329
|
-
{
|
330
|
-
if (!constructing_path) rb_raise(rb_eArgError, "Sorry: must be constructing path when call closepath");
|
331
|
-
if (writing_file) fprintf(TF, "h\n");
|
332
|
-
have_current_point = false;
|
333
|
-
p = NULL;
|
334
|
-
}
|
335
|
-
|
336
|
-
VALUE FM_close_path(VALUE fmkr)
|
337
|
-
{
|
338
|
-
c_closepath(Get_FM(fmkr));
|
339
|
-
return fmkr;
|
340
|
-
}
|
341
|
-
|
342
|
-
void c_append_arc(FM *p, double x_start, double y_start, double x_corner, double y_corner,
|
343
|
-
double x_end, double y_end, double radius)
|
344
|
-
{
|
345
|
-
ARE_OK_NUMBERS(x_start,y_start);
|
346
|
-
ARE_OK_NUMBERS(x_corner,y_corner);
|
347
|
-
ARE_OK_NUMBERS(x_end,y_end);
|
348
|
-
|
349
|
-
double x0, y0, x1, y1, x2, y2, x3, y3, udx, udy, vdx, vdy, wdx, wdy, len, x_center, y_center, tmp;
|
350
|
-
double psi, sin_psi, cos_psi, theta, cos_alpha, sin_alpha;
|
351
|
-
udx = x_start - x_corner; udy = y_start - y_corner;
|
352
|
-
vdx = x_end - x_corner; vdy = y_end - y_corner;
|
353
|
-
len = sqrt(udx*udx + udy*udy); udx /= len; udy /= len; // u is unit vector from corner to start
|
354
|
-
len = sqrt(vdx*vdx + vdy*vdy); vdx /= len; vdy /= len; // v is unit vector from corner to end
|
355
|
-
cos_psi = udx*vdx + udy*vdy; sin_psi = udy * vdx - udx * vdy;
|
356
|
-
psi = atan2(sin_psi, cos_psi); // psi is angle between u and v
|
357
|
-
if (psi > PI) psi = 2*PI - psi;
|
358
|
-
theta = PI - psi; // theta is opening angle for the arc
|
359
|
-
while (theta < 0) theta += 2*PI;
|
360
|
-
if (theta >= PI) rb_raise(rb_eArgError, "Sorry: invalid control point for arc");
|
361
|
-
// first compute control points for arc of opening theta with unit radius, bisected by positive x axis
|
362
|
-
// based on note by Richard DeVeneza, "How to determine the control points of a Bezier curve that
|
363
|
-
// approximates a small circular arc", Nov 2004.
|
364
|
-
x0 = cos(theta/2); y0 = sin(theta/2); x3 = x0; y3 = -y0;
|
365
|
-
x1 = (4-x0)/3; y1 = (1-x0)*(3-x0)/(3*y0); x2 = x1; y2 = -y1;
|
366
|
-
if (sin_psi > 0) { y0 = -y0; y1 = -y1; y2 = -y2; y3 = -y3; }
|
367
|
-
wdx = udx + vdx; wdy = udy + vdy;
|
368
|
-
len = sqrt(wdx*wdx + wdy*wdy); wdx /= len; wdy /= len; // w is unit vector bisecting the corner angle
|
369
|
-
cos_alpha = -wdx; sin_alpha = -wdy; // need to rotate the arc by alpha
|
370
|
-
x_center = x_corner + radius * wdx / x0;
|
371
|
-
y_center = y_corner + radius * wdy / x0;
|
372
|
-
// then translate arc to x_center, y_center
|
373
|
-
tmp = x0; x0 = x0*cos_alpha - y0*sin_alpha; y0 = y0*cos_alpha + tmp*sin_alpha;
|
374
|
-
tmp = x1; x1 = x1*cos_alpha - y1*sin_alpha; y1 = y1*cos_alpha + tmp*sin_alpha;
|
375
|
-
tmp = x2; x2 = x2*cos_alpha - y2*sin_alpha; y2 = y2*cos_alpha + tmp*sin_alpha;
|
376
|
-
tmp = x3; x3 = x3*cos_alpha - y3*sin_alpha; y3 = y3*cos_alpha + tmp*sin_alpha;
|
377
|
-
x0 *= radius; y0 *= radius;
|
378
|
-
x1 *= radius; y1 *= radius;
|
379
|
-
x2 *= radius; y2 *= radius;
|
380
|
-
x3 *= radius; y3 *= radius;
|
381
|
-
x0 += x_center; y0 += y_center;
|
382
|
-
x1 += x_center; y1 += y_center;
|
383
|
-
x2 += x_center; y2 += y_center;
|
384
|
-
x3 += x_center; y3 += y_center;
|
385
|
-
if (have_current_point) c_lineto(p,x0,y0);
|
386
|
-
else c_moveto(p,x0,y0);
|
387
|
-
c_curveto(p,x1,y1,x2,y2,x3,y3);
|
388
|
-
}
|
389
|
-
|
390
|
-
double Get_Arc_Radius(FM *p, VALUE dx, VALUE dy)
|
391
|
-
{
|
392
|
-
dx = rb_Float(dx);
|
393
|
-
dy = rb_Float(dy);
|
394
|
-
double rx = NUM2DBL(dx), ry = NUM2DBL(dy);
|
395
|
-
rx = convert_figure_to_output_dx(p,rx);
|
396
|
-
ry = convert_figure_to_output_dy(p,ry);
|
397
|
-
if (rx < 0) rx = -rx;
|
398
|
-
if (ry < 0) ry = -ry;
|
399
|
-
return MIN(rx,ry);
|
400
|
-
}
|
401
|
-
|
402
|
-
VALUE FM_append_arc_to_path(VALUE fmkr, VALUE x_start, VALUE y_start, VALUE x_corner, VALUE y_corner,
|
403
|
-
VALUE x_end, VALUE y_end, VALUE dx, VALUE dy)
|
404
|
-
{
|
405
|
-
FM *p = Get_FM(fmkr);
|
406
|
-
x_start = rb_Float(x_start);
|
407
|
-
y_start = rb_Float(y_start);
|
408
|
-
x_corner = rb_Float(x_corner);
|
409
|
-
y_corner = rb_Float(y_corner);
|
410
|
-
x_end = rb_Float(x_end);
|
411
|
-
y_end = rb_Float(y_end);
|
412
|
-
c_append_arc(p,
|
413
|
-
convert_figure_to_output_x(p,NUM2DBL(x_start)), convert_figure_to_output_y(p,NUM2DBL(y_start)),
|
414
|
-
convert_figure_to_output_x(p,NUM2DBL(x_corner)), convert_figure_to_output_y(p,NUM2DBL(y_corner)),
|
415
|
-
convert_figure_to_output_x(p,NUM2DBL(x_end)), convert_figure_to_output_y(p,NUM2DBL(y_end)),
|
416
|
-
Get_Arc_Radius(p,dx,dy));
|
417
|
-
return fmkr;
|
418
|
-
}
|
419
|
-
|
420
|
-
void c_append_rect(FM *p, double x, double y, double width, double height)
|
421
|
-
{
|
422
|
-
c_moveto(p,x,y);
|
423
|
-
c_lineto(p,x+width,y);
|
424
|
-
c_lineto(p,x+width,y+height);
|
425
|
-
c_lineto(p,x,y+height);
|
426
|
-
c_closepath(p);
|
427
|
-
}
|
428
|
-
|
429
|
-
VALUE FM_append_rect_to_path(VALUE fmkr, VALUE x, VALUE y, VALUE width, VALUE height)
|
430
|
-
{
|
431
|
-
FM *p = Get_FM(fmkr);
|
432
|
-
x = rb_Float(x);
|
433
|
-
y = rb_Float(y);
|
434
|
-
width = rb_Float(width);
|
435
|
-
height = rb_Float(height);
|
436
|
-
c_append_rect(p,
|
437
|
-
convert_figure_to_output_x(p,NUM2DBL(x)), convert_figure_to_output_y(p,NUM2DBL(y)),
|
438
|
-
convert_figure_to_output_dx(p,NUM2DBL(width)), convert_figure_to_output_dy(p,NUM2DBL(height)));
|
439
|
-
return fmkr;
|
440
|
-
}
|
441
|
-
|
442
|
-
void c_append_rounded_rect(FM *p, double x, double y, double width, double height, double radius)
|
443
|
-
{
|
444
|
-
double xc = x + width/2, yc = y + height/2, xp = x + width, yp = y + height;
|
445
|
-
c_moveto(p,xc,y);
|
446
|
-
c_append_arc(p,xc,y, xp,y, xp,yc, radius);
|
447
|
-
c_append_arc(p,xp,yc, xp,yp, xc,yp, radius);
|
448
|
-
c_append_arc(p,xc,yp, x,yp, x,yc, radius);
|
449
|
-
c_append_arc(p,x,yc, x,y, xc,y, radius);
|
450
|
-
c_closepath(p);
|
451
|
-
}
|
452
|
-
|
453
|
-
VALUE FM_append_rounded_rect_to_path(VALUE fmkr, VALUE x, VALUE y, VALUE width, VALUE height, VALUE dx, VALUE dy)
|
454
|
-
{
|
455
|
-
FM *p = Get_FM(fmkr);
|
456
|
-
x = rb_Float(x);
|
457
|
-
y = rb_Float(y);
|
458
|
-
width = rb_Float(width);
|
459
|
-
height = rb_Float(height);
|
460
|
-
c_append_rounded_rect(p,
|
461
|
-
convert_figure_to_output_x(p,NUM2DBL(x)), convert_figure_to_output_y(p,NUM2DBL(y)),
|
462
|
-
convert_figure_to_output_dx(p,NUM2DBL(width)), convert_figure_to_output_dy(p,NUM2DBL(height)),
|
463
|
-
Get_Arc_Radius(p,dx,dy));
|
464
|
-
return fmkr;
|
465
|
-
}
|
466
|
-
|
467
|
-
#define ROTATE90(x,y) tmp = x; x = y; y = -tmp;
|
468
|
-
#define TRANSFORM(xp,yp,x,y) xp = a*(x)+c*(y)+e; yp = b*(x)+d*(y)+f;
|
469
|
-
|
470
|
-
void c_append_oval(FM *p, double x, double y, double dx, double dy, double angle)
|
471
|
-
{
|
472
|
-
double cs = cos(angle/RADIANS_TO_DEGREES), sn = sin(angle/RADIANS_TO_DEGREES);
|
473
|
-
double a = cs*dx, b = sn*dx, c = -sn*dy, d = cs*dy, e = x, f = y;
|
474
|
-
double x0, y0, x1, y1, x2, y2, x3, y3, x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p, tmp;
|
475
|
-
int i;
|
476
|
-
x0 = 0.707107; y0 = 0.707107; x3 = x0; y3 = -y0;
|
477
|
-
x1 = 1.09763; y1 = 0.316582; x2 = x1; y2 = -y1;
|
478
|
-
TRANSFORM(x0p,y0p,x0,y0)
|
479
|
-
TRANSFORM(x1p,y1p,x1,y1)
|
480
|
-
TRANSFORM(x2p,y2p,x2,y2)
|
481
|
-
TRANSFORM(x3p,y3p,x3,y3)
|
482
|
-
c_moveto(p,x0p,y0p);
|
483
|
-
c_curveto(p,x1p,y1p,x2p,y2p,x3p,y3p);
|
484
|
-
for (i = 0; i < 3; i++) {
|
485
|
-
ROTATE90(x0,y0)
|
486
|
-
ROTATE90(x1,y1)
|
487
|
-
ROTATE90(x2,y2)
|
488
|
-
ROTATE90(x3,y3)
|
489
|
-
TRANSFORM(x0p,y0p,x0,y0)
|
490
|
-
TRANSFORM(x1p,y1p,x1,y1)
|
491
|
-
TRANSFORM(x2p,y2p,x2,y2)
|
492
|
-
TRANSFORM(x3p,y3p,x3,y3)
|
493
|
-
c_curveto(p,x1p,y1p,x2p,y2p,x3p,y3p);
|
494
|
-
}
|
495
|
-
c_closepath(p);
|
496
|
-
}
|
497
|
-
|
498
|
-
VALUE FM_append_oval_to_path(VALUE fmkr, VALUE x, VALUE y, VALUE dx, VALUE dy, VALUE angle)
|
499
|
-
{
|
500
|
-
FM *p = Get_FM(fmkr);
|
501
|
-
x = rb_Float(x);
|
502
|
-
y = rb_Float(y);
|
503
|
-
dx = rb_Float(dx);
|
504
|
-
dy = rb_Float(dy);
|
505
|
-
angle = rb_Float(angle);
|
506
|
-
c_append_oval(p,
|
507
|
-
convert_figure_to_output_x(p,NUM2DBL(x)), convert_figure_to_output_y(p,NUM2DBL(y)),
|
508
|
-
convert_figure_to_output_dx(p,NUM2DBL(dx)), convert_figure_to_output_dy(p,NUM2DBL(dy)),
|
509
|
-
NUM2DBL(angle));
|
510
|
-
return fmkr;
|
511
|
-
}
|
512
|
-
|
513
|
-
VALUE FM_append_circle_to_path(VALUE fmkr, VALUE x, VALUE y, VALUE dx)
|
514
|
-
{
|
515
|
-
FM *p = Get_FM(fmkr);
|
516
|
-
x = rb_Float(x);
|
517
|
-
y = rb_Float(y);
|
518
|
-
dx = rb_Float(dx);
|
519
|
-
double s = convert_figure_to_output_dx(p,NUM2DBL(dx));
|
520
|
-
c_append_oval(p,
|
521
|
-
convert_figure_to_output_x(p,NUM2DBL(x)), convert_figure_to_output_y(p,NUM2DBL(y)),
|
522
|
-
s, s, 0.0);
|
523
|
-
return fmkr;
|
524
|
-
}
|
525
|
-
|
526
|
-
VALUE FM_append_points_to_path(VALUE fmkr, VALUE x_vec, VALUE y_vec)
|
527
|
-
{
|
528
|
-
FM *p = Get_FM(fmkr);
|
529
|
-
long xlen, ylen, i;
|
530
|
-
double x0, y0;
|
531
|
-
double *xs = Dvector_Data_for_Read(x_vec, &xlen);
|
532
|
-
double *ys = Dvector_Data_for_Read(y_vec, &ylen);
|
533
|
-
if (xlen != ylen) rb_raise(rb_eArgError, "Sorry: must have same number xs and ys for append_points");
|
534
|
-
if (xlen <= 0) return fmkr;
|
535
|
-
x0 = convert_figure_to_output_x(p,xs[0]); y0 = convert_figure_to_output_y(p,ys[0]);
|
536
|
-
if (have_current_point) c_lineto(p,x0,y0);
|
537
|
-
else c_moveto(p,x0,y0);
|
538
|
-
for (i=1; i<xlen; i++)
|
539
|
-
c_lineto(p,convert_figure_to_output_x(p,xs[i]), convert_figure_to_output_y(p,ys[i]));
|
540
|
-
return fmkr;
|
541
|
-
}
|
542
|
-
|
543
|
-
VALUE FM_private_append_points_with_gaps_to_path(VALUE fmkr, VALUE x_vec, VALUE y_vec, VALUE gaps, VALUE close_gaps)
|
544
|
-
// where there's a gap, do a moveto instead of a lineto
|
545
|
-
{
|
546
|
-
if (gaps == Qnil) return FM_append_points_to_path(fmkr, x_vec, y_vec);
|
547
|
-
FM *p = Get_FM(fmkr);
|
548
|
-
long xlen, ylen, glen, i, j;
|
549
|
-
double x0, y0;
|
550
|
-
double *xs = Dvector_Data_for_Read(x_vec, &xlen);
|
551
|
-
double *ys = Dvector_Data_for_Read(y_vec, &ylen);
|
552
|
-
double *gs = Dvector_Data_for_Read(gaps, &glen);
|
553
|
-
bool do_close = (close_gaps == Qtrue);
|
554
|
-
if (xlen != ylen) rb_raise(rb_eArgError, "Sorry: must have same number xs and ys for append_points_with_gaps");
|
555
|
-
if (xlen <= 0) return fmkr;
|
556
|
-
x0 = convert_figure_to_output_x(p,xs[0]); y0 = convert_figure_to_output_y(p,ys[0]);
|
557
|
-
if (have_current_point) c_lineto(p,x0,y0);
|
558
|
-
else c_moveto(p,x0,y0);
|
559
|
-
for (i = 1, j = 0; j < glen; j++) {
|
560
|
-
int gap_start = ROUND(gs[j]);
|
561
|
-
if (gap_start == xlen) break;
|
562
|
-
if (gap_start > xlen)
|
563
|
-
rb_raise(rb_eArgError, "Sorry: gap value (%i) too large for vectors of length (%i)", gap_start, xlen);
|
564
|
-
while (i < gap_start) {
|
565
|
-
c_lineto(p,convert_figure_to_output_x(p,xs[i]), convert_figure_to_output_y(p,ys[i]));
|
566
|
-
i++;
|
567
|
-
}
|
568
|
-
if (do_close) c_closepath(p);
|
569
|
-
c_moveto(p,convert_figure_to_output_x(p,xs[i]), convert_figure_to_output_y(p,ys[i]));
|
570
|
-
i++;
|
571
|
-
}
|
572
|
-
while (i < xlen) {
|
573
|
-
c_lineto(p,convert_figure_to_output_x(p,xs[i]), convert_figure_to_output_y(p,ys[i]));
|
574
|
-
i++;
|
575
|
-
}
|
576
|
-
if (do_close) c_closepath(p);
|
577
|
-
return fmkr;
|
578
|
-
}
|
579
|
-
|
580
|
-
/* Path painting operators */
|
581
|
-
|
582
|
-
VALUE FM_stroke(VALUE fmkr)
|
583
|
-
{
|
584
|
-
if (!constructing_path) return fmkr;
|
585
|
-
if (writing_file) fprintf(TF, "S\n");
|
586
|
-
have_current_point = constructing_path = false;
|
587
|
-
return fmkr;
|
588
|
-
}
|
589
|
-
|
590
|
-
VALUE FM_close_and_stroke(VALUE fmkr)
|
591
|
-
{
|
592
|
-
if (!constructing_path) return fmkr;
|
593
|
-
if (writing_file) fprintf(TF, "s\n");
|
594
|
-
have_current_point = constructing_path = false;
|
595
|
-
return fmkr;
|
596
|
-
}
|
597
|
-
|
598
|
-
VALUE FM_fill(VALUE fmkr)
|
599
|
-
{
|
600
|
-
if (!constructing_path) return fmkr;
|
601
|
-
if (writing_file) fprintf(TF, "f\n");
|
602
|
-
have_current_point = constructing_path = false;
|
603
|
-
return fmkr;
|
604
|
-
}
|
605
|
-
|
606
|
-
VALUE FM_discard_path(VALUE fmkr)
|
607
|
-
{
|
608
|
-
if (!constructing_path) return fmkr;
|
609
|
-
if (writing_file) fprintf(TF, "n\n");
|
610
|
-
have_current_point = constructing_path = false;
|
611
|
-
return fmkr;
|
612
|
-
}
|
613
|
-
|
614
|
-
VALUE FM_eofill(VALUE fmkr)
|
615
|
-
{
|
616
|
-
if (!constructing_path) return fmkr;
|
617
|
-
if (writing_file) fprintf(TF, "f*\n");
|
618
|
-
have_current_point = constructing_path = false;
|
619
|
-
return fmkr;
|
620
|
-
}
|
621
|
-
|
622
|
-
VALUE FM_fill_and_stroke(VALUE fmkr)
|
623
|
-
{
|
624
|
-
if (!constructing_path) return fmkr;
|
625
|
-
if (writing_file) fprintf(TF, "B\n");
|
626
|
-
have_current_point = constructing_path = false;
|
627
|
-
return fmkr;
|
628
|
-
}
|
629
|
-
|
630
|
-
VALUE FM_eofill_and_stroke(VALUE fmkr)
|
631
|
-
{
|
632
|
-
if (!constructing_path) return fmkr;
|
633
|
-
if (writing_file) fprintf(TF, "B*\n");
|
634
|
-
have_current_point = constructing_path = false;
|
635
|
-
return fmkr;
|
636
|
-
}
|
637
|
-
|
638
|
-
VALUE FM_close_fill_and_stroke(VALUE fmkr)
|
639
|
-
{
|
640
|
-
if (!constructing_path) return fmkr;
|
641
|
-
if (writing_file) fprintf(TF, "b\n");
|
642
|
-
have_current_point = constructing_path = false;
|
643
|
-
return fmkr;
|
644
|
-
}
|
645
|
-
|
646
|
-
VALUE FM_close_eofill_and_stroke(VALUE fmkr)
|
647
|
-
{
|
648
|
-
if (!constructing_path) return fmkr;
|
649
|
-
if (writing_file) fprintf(TF, "b*\n");
|
650
|
-
have_current_point = constructing_path = false;
|
651
|
-
return fmkr;
|
652
|
-
}
|
653
|
-
|
654
|
-
void c_clip(FM *p)
|
655
|
-
{
|
656
|
-
if (!constructing_path) return;
|
657
|
-
if (writing_file) fprintf(TF, "W n\n");
|
658
|
-
have_current_point = constructing_path = false;
|
659
|
-
p = NULL;
|
660
|
-
}
|
661
|
-
|
662
|
-
VALUE FM_clip(VALUE fmkr)
|
663
|
-
{
|
664
|
-
c_clip(Get_FM(fmkr));
|
665
|
-
return fmkr;
|
666
|
-
}
|
667
|
-
|
668
|
-
VALUE FM_eoclip(VALUE fmkr)
|
669
|
-
{
|
670
|
-
if (!constructing_path) return fmkr;
|
671
|
-
if (writing_file) fprintf(TF, "W* n\n");
|
672
|
-
have_current_point = constructing_path = false;
|
673
|
-
return fmkr;
|
674
|
-
}
|
675
|
-
|
676
|
-
VALUE FM_fill_and_clip(VALUE fmkr)
|
677
|
-
{
|
678
|
-
if (!constructing_path) return fmkr;
|
679
|
-
if (writing_file) fprintf(TF, "q f Q\n");
|
680
|
-
c_clip(Get_FM(fmkr));
|
681
|
-
return fmkr;
|
682
|
-
}
|
683
|
-
|
684
|
-
VALUE FM_stroke_and_clip(VALUE fmkr)
|
685
|
-
{
|
686
|
-
if (!constructing_path) return fmkr;
|
687
|
-
if (writing_file) fprintf(TF, "q S Q\n");
|
688
|
-
c_clip(Get_FM(fmkr));
|
689
|
-
return fmkr;
|
690
|
-
}
|
691
|
-
|
692
|
-
VALUE FM_fill_stroke_and_clip(VALUE fmkr)
|
693
|
-
{
|
694
|
-
if (!constructing_path) return fmkr;
|
695
|
-
if (writing_file) fprintf(TF, "q B Q\n");
|
696
|
-
c_clip(Get_FM(fmkr));
|
697
|
-
return fmkr;
|
698
|
-
}
|
699
|
-
|
700
|
-
/* Combination Path Constructing and Using */
|
701
|
-
|
702
|
-
VALUE FM_stroke_line(VALUE fmkr, VALUE x1, VALUE y1, VALUE x2, VALUE y2)
|
703
|
-
{
|
704
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling stroke_line");
|
705
|
-
FM_move_to_point(fmkr, x1, y1);
|
706
|
-
FM_append_point_to_path(fmkr, x2, y2);
|
707
|
-
FM_stroke(fmkr);
|
708
|
-
return fmkr;
|
709
|
-
}
|
710
|
-
|
711
|
-
VALUE FM_fill_rect(VALUE fmkr, VALUE x, VALUE y, VALUE width, VALUE height)
|
712
|
-
{
|
713
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling fill_rect");
|
714
|
-
FM_append_rect_to_path(fmkr, x, y, width, height);
|
715
|
-
FM_fill(fmkr);
|
716
|
-
return fmkr;
|
717
|
-
}
|
718
|
-
|
719
|
-
VALUE FM_stroke_rect(VALUE fmkr, VALUE x, VALUE y, VALUE width, VALUE height)
|
720
|
-
{
|
721
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling stroke_rect");
|
722
|
-
FM_append_rect_to_path(fmkr, x, y, width, height);
|
723
|
-
FM_stroke(fmkr);
|
724
|
-
return fmkr;
|
725
|
-
}
|
726
|
-
|
727
|
-
VALUE FM_fill_and_stroke_rect(VALUE fmkr, VALUE x, VALUE y, VALUE width, VALUE height)
|
728
|
-
{
|
729
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling fill_and_stroke_rect");
|
730
|
-
FM_append_rect_to_path(fmkr, x, y, width, height);
|
731
|
-
FM_fill_and_stroke(fmkr);
|
732
|
-
return fmkr;
|
733
|
-
}
|
734
|
-
|
735
|
-
void c_clip_rect(FM *p, double x, double y, double width, double height) // in output coords
|
736
|
-
{
|
737
|
-
double clip_left=x, clip_right, clip_top, clip_bottom=y, clip_width=width, clip_height=height;
|
738
|
-
if (clip_width < 0.0) { clip_right = clip_left; clip_width = -clip_width; clip_left -= clip_width; }
|
739
|
-
else clip_right = clip_left + clip_width;
|
740
|
-
if (clip_height < 0.0) { clip_top = clip_bottom; clip_height = -clip_height; clip_bottom -= clip_height; }
|
741
|
-
else clip_top = clip_bottom + clip_height;
|
742
|
-
c_append_rect(p, clip_left, clip_bottom, clip_width, clip_height);
|
743
|
-
c_clip(p);
|
744
|
-
if (clip_left > p->clip_left) p->clip_left = clip_left;
|
745
|
-
if (clip_bottom > p->clip_bottom) p->clip_bottom = clip_bottom;
|
746
|
-
if (clip_right < p->clip_right) p->clip_right = clip_right;
|
747
|
-
if (clip_top < p->clip_top) p->clip_top = clip_top;
|
748
|
-
}
|
749
|
-
|
750
|
-
VALUE FM_clip_rect(VALUE fmkr, VALUE x, VALUE y, VALUE width, VALUE height)
|
751
|
-
{
|
752
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling clip_rect");
|
753
|
-
FM *p = Get_FM(fmkr);
|
754
|
-
x = rb_Float(x);
|
755
|
-
y = rb_Float(y);
|
756
|
-
width = rb_Float(width);
|
757
|
-
height = rb_Float(height);
|
758
|
-
c_clip_rect(p,
|
759
|
-
convert_figure_to_output_x(p,NUM2DBL(x)), convert_figure_to_output_y(p,NUM2DBL(y)),
|
760
|
-
convert_figure_to_output_dx(p,NUM2DBL(width)), convert_figure_to_output_dy(p,NUM2DBL(height)));
|
761
|
-
return fmkr;
|
762
|
-
}
|
763
|
-
|
764
|
-
VALUE FM_clip_oval(VALUE fmkr, VALUE x, VALUE y, VALUE dx, VALUE dy, VALUE angle)
|
765
|
-
{
|
766
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling clip_oval");
|
767
|
-
FM_append_oval_to_path(fmkr, x, y, dx, dy, angle);
|
768
|
-
FM_clip(fmkr);
|
769
|
-
return fmkr;
|
770
|
-
}
|
771
|
-
|
772
|
-
VALUE FM_fill_oval(VALUE fmkr, VALUE x, VALUE y, VALUE dx, VALUE dy, VALUE angle)
|
773
|
-
{
|
774
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling fill_oval");
|
775
|
-
FM_append_oval_to_path(fmkr, x, y, dx, dy, angle);
|
776
|
-
FM_fill(fmkr);
|
777
|
-
return fmkr;
|
778
|
-
}
|
779
|
-
|
780
|
-
VALUE FM_stroke_oval(VALUE fmkr, VALUE x, VALUE y, VALUE dx, VALUE dy, VALUE angle)
|
781
|
-
{
|
782
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling stroke_oval");
|
783
|
-
FM_append_oval_to_path(fmkr, x, y, dx, dy, angle);
|
784
|
-
FM_stroke(fmkr);
|
785
|
-
return fmkr;
|
786
|
-
}
|
787
|
-
|
788
|
-
VALUE FM_fill_and_stroke_oval(VALUE fmkr, VALUE x, VALUE y, VALUE dx, VALUE dy, VALUE angle)
|
789
|
-
{
|
790
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling fill_and_stroke_oval");
|
791
|
-
FM_append_oval_to_path(fmkr, x, y, dx, dy, angle);
|
792
|
-
FM_fill_and_stroke(fmkr);
|
793
|
-
return fmkr;
|
794
|
-
}
|
795
|
-
|
796
|
-
VALUE FM_clip_rounded_rect(VALUE fmkr, VALUE x, VALUE y, VALUE width, VALUE height, VALUE dx, VALUE dy)
|
797
|
-
{
|
798
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling clip_rounded_rect");
|
799
|
-
FM_append_rounded_rect_to_path(fmkr, x, y, width, height, dx, dy);
|
800
|
-
FM_clip(fmkr);
|
801
|
-
return fmkr;
|
802
|
-
}
|
803
|
-
|
804
|
-
VALUE FM_fill_rounded_rect(VALUE fmkr, VALUE x, VALUE y, VALUE width, VALUE height, VALUE dx, VALUE dy)
|
805
|
-
{
|
806
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling fill_rounded_rect");
|
807
|
-
FM_append_rounded_rect_to_path(fmkr, x, y, width, height, dx, dy);
|
808
|
-
FM_fill(fmkr);
|
809
|
-
return fmkr;
|
810
|
-
}
|
811
|
-
|
812
|
-
VALUE FM_stroke_rounded_rect(VALUE fmkr, VALUE x, VALUE y, VALUE width, VALUE height, VALUE dx, VALUE dy)
|
813
|
-
{
|
814
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling stroke_rounded_rect");
|
815
|
-
FM_append_rounded_rect_to_path(fmkr, x, y, width, height, dx, dy);
|
816
|
-
FM_stroke(fmkr);
|
817
|
-
return fmkr;
|
818
|
-
}
|
819
|
-
|
820
|
-
VALUE FM_fill_and_stroke_rounded_rect(VALUE fmkr, VALUE x, VALUE y, VALUE width, VALUE height, VALUE dx, VALUE dy)
|
821
|
-
{
|
822
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling fill_and_stroke_rounded_rect");
|
823
|
-
FM_append_rounded_rect_to_path(fmkr, x, y, width, height, dx, dy);
|
824
|
-
FM_fill_and_stroke(fmkr);
|
825
|
-
return fmkr;
|
826
|
-
}
|
827
|
-
|
828
|
-
VALUE FM_clip_circle(VALUE fmkr, VALUE x, VALUE y, VALUE dx)
|
829
|
-
{
|
830
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling clip_circle");
|
831
|
-
FM_append_circle_to_path(fmkr, x, y, dx);
|
832
|
-
FM_clip(fmkr);
|
833
|
-
return fmkr;
|
834
|
-
}
|
835
|
-
|
836
|
-
VALUE FM_fill_circle(VALUE fmkr, VALUE x, VALUE y, VALUE dx)
|
837
|
-
{
|
838
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling fill_circle");
|
839
|
-
FM_append_circle_to_path(fmkr, x, y, dx);
|
840
|
-
FM_fill(fmkr);
|
841
|
-
return fmkr;
|
842
|
-
}
|
843
|
-
|
844
|
-
VALUE FM_stroke_circle(VALUE fmkr, VALUE x, VALUE y, VALUE dx)
|
845
|
-
{
|
846
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling stroke_circle");
|
847
|
-
FM_append_circle_to_path(fmkr, x, y, dx);
|
848
|
-
FM_stroke(fmkr);
|
849
|
-
return fmkr;
|
850
|
-
}
|
851
|
-
|
852
|
-
VALUE FM_fill_and_stroke_circle(VALUE fmkr, VALUE x, VALUE y, VALUE dx)
|
853
|
-
{
|
854
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling fill_and_stroke_circle");
|
855
|
-
FM_append_circle_to_path(fmkr, x, y, dx);
|
856
|
-
FM_fill_and_stroke(fmkr);
|
857
|
-
return fmkr;
|
858
|
-
}
|
859
|
-
|
860
|
-
static void c_append_frame(FM *p, bool clip)
|
861
|
-
{
|
862
|
-
double frame_left = convert_page_to_output_x(p, p->frame_left);
|
863
|
-
double frame_bottom = convert_page_to_output_y(p, p->frame_bottom);
|
864
|
-
double frame_width = convert_page_to_output_dx(p, p->frame_width);
|
865
|
-
double frame_height = convert_page_to_output_dy(p, p->frame_height);
|
866
|
-
double frame_right = frame_left + frame_width;
|
867
|
-
double frame_top = frame_bottom + frame_height;
|
868
|
-
c_append_rect(p, frame_left, frame_bottom, frame_width, frame_height);
|
869
|
-
if (!clip) return;
|
870
|
-
if (frame_left > p->clip_left) p->clip_left = frame_left;
|
871
|
-
if (frame_bottom > p->clip_bottom) p->clip_bottom = frame_bottom;
|
872
|
-
if (frame_right < p->clip_right) p->clip_right = frame_right;
|
873
|
-
if (frame_top < p->clip_top) p->clip_top = frame_top;
|
874
|
-
}
|
875
|
-
|
876
|
-
VALUE FM_append_frame_to_path(VALUE fmkr)
|
877
|
-
{
|
878
|
-
FM *p = Get_FM(fmkr);
|
879
|
-
c_append_frame(p, false);
|
880
|
-
return fmkr;
|
881
|
-
}
|
882
|
-
|
883
|
-
VALUE FM_fill_frame(VALUE fmkr)
|
884
|
-
{
|
885
|
-
FM *p = Get_FM(fmkr);
|
886
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling fill_frame");
|
887
|
-
c_append_frame(p, false); FM_fill(fmkr);
|
888
|
-
return fmkr;
|
889
|
-
}
|
890
|
-
|
891
|
-
VALUE FM_stroke_frame(VALUE fmkr)
|
892
|
-
{
|
893
|
-
FM *p = Get_FM(fmkr);
|
894
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling stroke_frame");
|
895
|
-
c_append_frame(p, false); FM_stroke(fmkr);
|
896
|
-
return fmkr;
|
897
|
-
}
|
898
|
-
|
899
|
-
VALUE FM_fill_and_stroke_frame(VALUE fmkr)
|
900
|
-
{
|
901
|
-
FM *p = Get_FM(fmkr);
|
902
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling fill_and_stroke_frame");
|
903
|
-
c_append_frame(p, false); FM_fill_and_stroke(fmkr);
|
904
|
-
return fmkr;
|
905
|
-
}
|
906
|
-
|
907
|
-
VALUE FM_clip_to_frame(VALUE fmkr)
|
908
|
-
{
|
909
|
-
FM *p = Get_FM(fmkr);
|
910
|
-
if (constructing_path) rb_raise(rb_eArgError, "Sorry: must finish with current path before calling clip_to_frame");
|
911
|
-
c_append_frame(p, true); FM_clip(fmkr);
|
912
|
-
return fmkr;
|
913
|
-
}
|