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.
Files changed (41) hide show
  1. data/Tioga_README +35 -10
  2. data/split/Dvector/dvector.c +264 -22
  3. data/split/Dvector/lib/Dvector_extras.rb +30 -2
  4. data/split/Flate/extconf.rb +1 -1
  5. data/split/Function/function.c +112 -2
  6. data/split/Tioga/figures.c +76 -77
  7. data/split/Tioga/figures.h +375 -490
  8. data/split/Tioga/generic.c +254 -0
  9. data/split/Tioga/generic.h +236 -0
  10. data/split/Tioga/init.c +434 -320
  11. data/split/Tioga/lib/Creating_Paths.rb +11 -1
  12. data/split/Tioga/lib/FigMkr.rb +263 -65
  13. data/split/Tioga/lib/Legends.rb +4 -2
  14. data/split/Tioga/lib/Markers.rb +3 -2
  15. data/split/Tioga/lib/Special_Paths.rb +22 -23
  16. data/split/Tioga/lib/TeX_Text.rb +79 -1
  17. data/split/Tioga/lib/TexPreamble.rb +14 -0
  18. data/split/Tioga/lib/Utils.rb +5 -1
  19. data/split/Tioga/pdfs.h +7 -45
  20. data/split/Tioga/{axes.c → shared/axes.c} +210 -197
  21. data/split/Tioga/{makers.c → shared/makers.c} +442 -211
  22. data/split/Tioga/{pdf_font_dicts.c → shared/pdf_font_dicts.c} +0 -0
  23. data/split/Tioga/shared/pdfcolor.c +628 -0
  24. data/split/Tioga/shared/pdfcoords.c +443 -0
  25. data/split/Tioga/{pdffile.c → shared/pdffile.c} +56 -52
  26. data/split/Tioga/{pdfimage.c → shared/pdfimage.c} +103 -211
  27. data/split/Tioga/shared/pdfpath.c +766 -0
  28. data/split/Tioga/{pdftext.c → shared/pdftext.c} +121 -99
  29. data/split/Tioga/shared/texout.c +524 -0
  30. data/split/Tioga/wrappers.c +489 -0
  31. data/split/Tioga/wrappers.h +259 -0
  32. data/split/extconf.rb +4 -0
  33. data/split/mkmf2.rb +12 -1
  34. data/tests/benchmark_dvector_reads.rb +112 -0
  35. data/tests/tc_Dvector.rb +35 -3
  36. data/tests/tc_Function.rb +32 -0
  37. metadata +65 -52
  38. data/split/Tioga/pdfcolor.c +0 -486
  39. data/split/Tioga/pdfcoords.c +0 -523
  40. data/split/Tioga/pdfpath.c +0 -913
  41. data/split/Tioga/texout.c +0 -380
@@ -0,0 +1,628 @@
1
+ /* pdfcolor.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
+ /* functions */
26
+
27
+ void Free_Functions()
28
+ {
29
+ Function_Info *fo;
30
+ while (functions_list != NULL) {
31
+ fo = functions_list;
32
+ functions_list = fo->next;
33
+ if (fo->lookup != NULL) free(fo->lookup);
34
+ free(fo);
35
+ }
36
+ }
37
+
38
+ static void Write_Sampled_Function(Function_Info *fo, int *ierr)
39
+ {
40
+ fprintf(OF, "%i 0 obj << /FunctionType 0\n", fo->obj_num);
41
+ fprintf(OF, "\t/Domain [0 1]\n");
42
+ fprintf(OF, "\t/Range [0 1 0 1 0 1]\n");
43
+ fprintf(OF, "\t/Size [%i]\n", fo->hival + 1);
44
+ fprintf(OF, "\t/BitsPerSample 8\n");
45
+ fprintf(OF, "\t/Order 1\n");
46
+ fprintf(OF, "\t/Length %i\n\t>>\nstream\n", fo->lookup_len);
47
+ if (fwrite(fo->lookup, 1, fo->lookup_len, OF) < fo->lookup_len) {
48
+ RAISE_ERROR("Error writing function sample data", ierr); return; }
49
+ fprintf(OF, "\nendstream\nendobj\n");
50
+ }
51
+
52
+ void Write_Functions(int *ierr)
53
+ {
54
+ Function_Info *fo;
55
+ for (fo = functions_list; fo != NULL; fo = fo->next) {
56
+ Record_Object_Offset(fo->obj_num);
57
+ Write_Sampled_Function(fo, ierr);
58
+ }
59
+ }
60
+
61
+ static int create_function(int hival, int lookup_len, unsigned char *lookup)
62
+ {
63
+ Function_Info *fo = (Function_Info *)calloc(1,sizeof(Function_Info));
64
+ fo->next = functions_list;
65
+ functions_list = fo;
66
+ fo->lookup = ALLOC_N_unsigned_char(lookup_len);
67
+ memcpy(fo->lookup, lookup, lookup_len);
68
+ fo->lookup_len = lookup_len;
69
+ fo->hival = hival;
70
+ fo->obj_num = next_available_object_number++;
71
+ return fo->obj_num;
72
+ }
73
+
74
+ /* Opacity */
75
+
76
+ void Free_Stroke_Opacities(void)
77
+ {
78
+ Stroke_Opacity_State *p;
79
+ while (stroke_opacities != NULL) {
80
+ p = stroke_opacities; stroke_opacities = p->next; free(p);
81
+ }
82
+ }
83
+
84
+ static int Get_Stroke_Opacity_XGS(double stroke_opacity)
85
+ {
86
+ Stroke_Opacity_State *p;
87
+ for (p = stroke_opacities; p != NULL; p = p->next) {
88
+ if (p->stroke_opacity == stroke_opacity) return p->gs_num;
89
+ }
90
+ p = (Stroke_Opacity_State *)calloc(1,sizeof(Stroke_Opacity_State));
91
+ p->stroke_opacity = stroke_opacity;
92
+ p->gs_num = next_available_gs_number++;
93
+ p->obj_num = next_available_object_number++;
94
+ p->next = stroke_opacities;
95
+ stroke_opacities = p;
96
+ return p->gs_num;
97
+ }
98
+
99
+ void c_stroke_opacity_set(OBJ_PTR fmkr, FM *p, double stroke_opacity, int *ierr)
100
+ { // /GSi gs for ExtGState obj with /CS set to stroke opacity val
101
+ if (constructing_path) {
102
+ RAISE_ERROR("Sorry: must not be constructing a path when change stroke opacity", ierr); return; }
103
+ if (stroke_opacity == p->stroke_opacity) return;
104
+ int gs_num = Get_Stroke_Opacity_XGS(stroke_opacity);
105
+ fprintf(TF, "/GS%i gs\n", gs_num);
106
+ p->stroke_opacity = stroke_opacity;
107
+ }
108
+
109
+ void Free_Fill_Opacities(void)
110
+ {
111
+ Fill_Opacity_State *p;
112
+ while (fill_opacities != NULL) {
113
+ p = fill_opacities; fill_opacities = p->next; free(p);
114
+ }
115
+ }
116
+
117
+ static int Get_Fill_Opacity_XGS(double fill_opacity)
118
+ {
119
+ Fill_Opacity_State *p;
120
+ for (p = fill_opacities; p != NULL; p = p->next) {
121
+ if (p->fill_opacity == fill_opacity) return p->gs_num;
122
+ }
123
+ p = (Fill_Opacity_State *)calloc(1,sizeof(Fill_Opacity_State));
124
+ p->fill_opacity = fill_opacity;
125
+ p->gs_num = next_available_gs_number++;
126
+ p->obj_num = next_available_object_number++;
127
+ p->next = fill_opacities;
128
+ fill_opacities = p;
129
+ return p->gs_num;
130
+ }
131
+
132
+ void c_fill_opacity_set(OBJ_PTR fmkr, FM *p, double fill_opacity, int *ierr)
133
+ { // /GSi gs for ExtGState obj with /cs set to fill opacity val
134
+ if (constructing_path) {
135
+ RAISE_ERROR("Sorry: must not be constructing a path when change fill opacity", ierr); return; }
136
+ if (fill_opacity == p->fill_opacity) return;
137
+ int gs_num = Get_Fill_Opacity_XGS(fill_opacity);
138
+ fprintf(TF, "/GS%i gs\n", gs_num);
139
+ p->fill_opacity = fill_opacity;
140
+ }
141
+
142
+ void Write_Stroke_Opacity_Objects(void)
143
+ {
144
+ Stroke_Opacity_State *p;
145
+ for (p = stroke_opacities; p != NULL; p = p->next) {
146
+ Record_Object_Offset(p->obj_num);
147
+ fprintf(OF, "%2i 0 obj << /Type /ExtGState /CA %g >> endobj\n", p->obj_num, p->stroke_opacity);
148
+ }
149
+ }
150
+
151
+ void Write_Fill_Opacity_Objects(void)
152
+ {
153
+ Fill_Opacity_State *p;
154
+ for (p = fill_opacities; p != NULL; p = p->next) {
155
+ Record_Object_Offset(p->obj_num);
156
+ fprintf(OF, "%2i 0 obj << /Type /ExtGState /ca %g >> endobj\n", p->obj_num, p->fill_opacity);
157
+ }
158
+ }
159
+
160
+ /* Shading */
161
+
162
+ void Free_Shadings()
163
+ {
164
+ Shading_Info *so;
165
+ while (shades_list != NULL) {
166
+ so = shades_list;
167
+ shades_list = so->next;
168
+ free(so);
169
+ }
170
+ }
171
+
172
+ void Write_Shadings(void)
173
+ {
174
+ Shading_Info *so;
175
+ for (so = shades_list; so != NULL; so = so->next) {
176
+ Record_Object_Offset(so->obj_num);
177
+ fprintf(OF, "%i 0 obj <<\n", so->obj_num);
178
+ if (so->axial) {
179
+ fprintf(OF, "\t/ShadingType 2\n\t/Coords [%0.2f %0.2f %0.2f %0.2f]\n",
180
+ so->x0, so->y0, so->x1, so->y1);
181
+ } else {
182
+ fprintf(OF, "\t/ShadingType 3\n\t/Coords [%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f]\n",
183
+ so->x0, so->y0, so->r0, so->x1, so->y1, so->r1);
184
+ }
185
+ if (so->extend_start || so->extend_end) fprintf(OF, "\t/Extend [ %s %s ]\n",
186
+ (so->extend_start)? "true" : "false", (so->extend_end)? "true" : "false");
187
+ fprintf(OF, "\t/ColorSpace /DeviceRGB\n");
188
+ fprintf(OF, "\t/Function %i 0 R\n", so->function);
189
+ fprintf(OF, ">> endobj\n");
190
+ }
191
+ }
192
+
193
+
194
+ static void c_axial_shading(FM *p, double x0, double y0, double x1, double y1,
195
+ int hival, int lookup_len, unsigned char *lookup, bool extend_start, bool extend_end)
196
+ {
197
+ Shading_Info *so = (Shading_Info *)calloc(1,sizeof(Shading_Info));
198
+ so->next = shades_list;
199
+ shades_list = so;
200
+ so->shade_num = next_available_shade_number++;
201
+ so->obj_num = next_available_object_number++;
202
+ so->function = create_function(hival, lookup_len, lookup);
203
+ so->axial = true;
204
+ so->x0 = x0;
205
+ so->y0 = y0;
206
+ so->x1 = x1;
207
+ so->y1 = y1;
208
+ so->extend_start = extend_start;
209
+ so->extend_end = extend_end;
210
+ fprintf(TF, "/Shade%i sh\n", so->shade_num);
211
+ }
212
+
213
+ void c_private_axial_shading(OBJ_PTR fmkr, FM *p, double x0, double y0, double x1, double y1,
214
+ OBJ_PTR colormap, bool extend_start, bool extend_end, int *ierr)
215
+ {
216
+ int len = Array_Len(colormap,ierr);
217
+ if (*ierr != 0) return;
218
+ if (len != 2) {
219
+ RAISE_ERROR("Sorry: colormap must be array [hivalue, lookup]", ierr); return; }
220
+ OBJ_PTR hival = Array_Entry(colormap,0,ierr);
221
+ OBJ_PTR lookup = Array_Entry(colormap,1,ierr);
222
+ int hi_value = Number_to_int(hival,ierr);
223
+ int lookup_len = String_Len(lookup,ierr);
224
+ unsigned char *lookup_ptr = (unsigned char *)(String_Ptr(lookup,ierr));
225
+ if (*ierr != 0) return;
226
+ c_axial_shading(p, convert_figure_to_output_x(p,x0), convert_figure_to_output_y(p,y0),
227
+ convert_figure_to_output_x(p,x1), convert_figure_to_output_y(p,y1),
228
+ hi_value, lookup_len, lookup_ptr, extend_start, extend_end);
229
+ }
230
+
231
+ static void c_radial_shading(FM *p, double x0, double y0, double r0, double x1, double y1, double r1,
232
+ int hival, int lookup_len, unsigned char *lookup,
233
+ double a, double b, double c, double d, double e, double f, bool extend_start, bool extend_end)
234
+ {
235
+ Shading_Info *so = (Shading_Info *)calloc(1,sizeof(Shading_Info));
236
+ so->next = shades_list;
237
+ shades_list = so;
238
+ so->shade_num = next_available_shade_number++;
239
+ so->obj_num = next_available_object_number++;
240
+ so->function = create_function(hival, lookup_len, lookup);
241
+ so->axial = false;
242
+ so->x0 = x0;
243
+ so->y0 = y0;
244
+ so->r0 = r0;
245
+ so->x1 = x1;
246
+ so->y1 = y1;
247
+ so->r1 = r1;
248
+ so->extend_start = extend_start;
249
+ so->extend_end = extend_end;
250
+ if (a != 1.0 || b != 0.0 || c != 0.0 || d != 1.0 || e != 0 || f != 0) {
251
+ fprintf(TF, "q %0.2f %0.2f %0.2f %0.2f %0.2f %0.2f cm /Shade%i sh Q\n",
252
+ a, b, c, d, e, f, so->shade_num);
253
+ } else {
254
+ fprintf(TF, "/Shade%i sh\n", so->shade_num);
255
+ }
256
+ }
257
+
258
+
259
+ void c_private_radial_shading(OBJ_PTR fmkr, FM *p,
260
+ double x0, double y0, double r0,
261
+ double x1, double y1, double r1, OBJ_PTR colormap,
262
+ double a, double b, double c, double d, bool extend_start, bool extend_end, int *ierr)
263
+ {
264
+ int len = Array_Len(colormap, ierr);
265
+ if (*ierr != 0) return;
266
+ if (len != 2) {
267
+ RAISE_ERROR("Sorry: colormap must be array [hivalue, lookup]", ierr); return; }
268
+ OBJ_PTR hival = Array_Entry(colormap, 0, ierr);
269
+ OBJ_PTR lookup = Array_Entry(colormap, 1, ierr);
270
+ int hi_value = Number_to_int(hival,ierr);
271
+ int lookup_len = String_Len(lookup,ierr);
272
+ unsigned char *lookup_ptr = (unsigned char *)(String_Ptr(lookup,ierr));
273
+ if (*ierr != 0) return;
274
+ c_radial_shading(p, x0, y0, r0, x1, y1, r1,
275
+ hi_value, lookup_len, lookup_ptr,
276
+ convert_figure_to_output_dx(p,a), convert_figure_to_output_dy(p,b),
277
+ convert_figure_to_output_dx(p,c), convert_figure_to_output_dy(p,d),
278
+ convert_figure_to_output_x(p,0.0), convert_figure_to_output_y(p,0.0),
279
+ extend_start, extend_end);
280
+ }
281
+
282
+ /* Colormaps
283
+ */
284
+
285
+ static double clr_value(double n1, double n2, double hue) // from plplot plctrl.c
286
+ {
287
+ double val;
288
+ while (hue >= 360.) hue -= 360.;
289
+ while (hue < 0.) hue += 360.;
290
+ if (hue < 60.) val = n1 + (n2 - n1) * hue / 60.;
291
+ else if (hue < 180.) val = n2;
292
+ else if (hue < 240.) val = n1 + (n2 - n1) * (240. - hue) / 60.;
293
+ else val = n1;
294
+ return (val);
295
+ }
296
+
297
+ static void convert_hls_to_rgb(double h, double l, double s, double *p_r, double *p_g, double *p_b) // from plplot plctrl.c
298
+ {
299
+ double m1, m2;
300
+ if (l <= .5) m2 = l * (s + 1.);
301
+ else m2 = l + s - l * s;
302
+ m1 = 2 * l - m2;
303
+ *p_r = clr_value(m1, m2, h + 120.);
304
+ *p_g = clr_value(m1, m2, h);
305
+ *p_b = clr_value(m1, m2, h - 120.);
306
+ }
307
+
308
+ static void convert_rgb_to_hls(double r, double g, double b, double *p_h, double *p_l, double *p_s) // from plplot plctrl.c
309
+ {
310
+ double h, l, s, d, rc, gc, bc, rgb_min, rgb_max;
311
+ rgb_min = MIN( r, MIN( g, b ));
312
+ rgb_max = MAX( r, MAX( g, b ));
313
+ l = (rgb_min+rgb_max) / 2.0;
314
+ if (rgb_min == rgb_max) s = h = 0;
315
+ else {
316
+ d = rgb_max - rgb_min;
317
+ if (l < 0.5) s = 0.5 * d / l;
318
+ else s = 0.5* d / (1.-l);
319
+ rc = (rgb_max-r) / d;
320
+ gc = (rgb_max-g) / d;
321
+ bc = (rgb_max-b) / d;
322
+ if (r == rgb_max) h = bc-gc;
323
+ else if (g == rgb_max) h = rc-bc+2;
324
+ else h = gc-rc-2;
325
+ h = h*60;
326
+ if (h < 0) h = h+360;
327
+ else if (h >= 360) h = h-360;
328
+ }
329
+ *p_h = h;
330
+ *p_l = l;
331
+ *p_s = s;
332
+ }
333
+
334
+ static double linear_interpolate(int num_pts, double *xs, double *ys, double x)
335
+ {
336
+ int i;
337
+ if (num_pts == 1) return ys[0];
338
+ for (i = 0; i < num_pts; i++) {
339
+ if (xs[i] <= x && x < xs[i+1]) {
340
+ return ys[i] + (ys[i+1]-ys[i])*(x-xs[i])/(xs[i+1]-xs[i]);
341
+ }
342
+ }
343
+ return ys[num_pts-1];
344
+ }
345
+
346
+ static OBJ_PTR c_create_colormap(FM *p, bool rgb_flag, int length,
347
+ int num_pts, double *ps, double *c1s, double *c2s, double *c3s, int *ierr)
348
+ {
349
+ int i;
350
+ if (ps[0] != 0.0 || ps[num_pts-1] != 1.0) {
351
+ RAISE_ERROR("Sorry: first control point for create colormap must be at 0.0 and last must be at 1.0", ierr); RETURN_NIL; }
352
+ for (i = 1; i < num_pts; i++) {
353
+ if (ps[i-1] > ps[i]) {
354
+ RAISE_ERROR("Sorry: control points for create colormap must be increasing from 0 to 1", ierr); RETURN_NIL; }
355
+ }
356
+ int j, buff_len = length * 3, hival = length-1;
357
+ unsigned char *buff;
358
+ buff = ALLOC_N_unsigned_char(buff_len);
359
+ for (j = 0, i = 0; j < length; j++) {
360
+ double x = j; x /= (length-1);
361
+ double c1, c2, c3, r, g, b;
362
+ c1 = linear_interpolate(num_pts, ps, c1s, x);
363
+ c2 = linear_interpolate(num_pts, ps, c2s, x);
364
+ c3 = linear_interpolate(num_pts, ps, c3s, x);
365
+ if (rgb_flag) { r = c1; g = c2; b = c3; }
366
+ else convert_hls_to_rgb(c1, c2, c3, &r, &g, &b);
367
+ buff[i++] = ROUND(hival * r);
368
+ buff[i++] = ROUND(hival * g);
369
+ buff[i++] = ROUND(hival * b);
370
+ }
371
+ OBJ_PTR lookup = String_New((char *)buff, buff_len);
372
+ free(buff);
373
+ OBJ_PTR result = Array_New(2);
374
+ Array_Store(result, 0, Integer_New(hival), ierr);
375
+ Array_Store(result, 1, lookup, ierr);
376
+ if (*ierr != 0) RETURN_NIL;
377
+ return result;
378
+ }
379
+
380
+ OBJ_PTR c_private_create_colormap(OBJ_PTR fmkr, FM *p, bool rgb, int length,
381
+ OBJ_PTR Ps, OBJ_PTR C1s, OBJ_PTR C2s, OBJ_PTR C3s, int *ierr)
382
+ {
383
+ /*
384
+ create mappings from 'position' (0 to 1) to color (in HLS or RGB color spaces)
385
+ the length parameter determines the number of entries in the color map (any integer between 2 and 256).
386
+ for rgb, the colors are given as (red, green, blue) intensities from 0.0 to 1.0
387
+ for hls, the colors are given as (hue, lightness, saturation)
388
+ lightness and saturation given as values from 0.0 to 1.0
389
+ hue given as degrees (0 to 360) around the color wheel from red->green->blue->red
390
+ Ps are the locations in (0 to 1) for the control points -- in increasing order
391
+ must have Ps[0] == 0.0 and Ps[num_ps-1] == 1.0
392
+ */
393
+ long p_len, c1_len, c2_len, c3_len;
394
+ double *p_ptr = Vector_Data_for_Read(Ps, &p_len, ierr);
395
+ if (*ierr != 0) return;
396
+ double *c1_ptr = Vector_Data_for_Read(C1s, &c1_len, ierr);
397
+ if (*ierr != 0) return;
398
+ double *c2_ptr = Vector_Data_for_Read(C2s, &c2_len, ierr);
399
+ if (*ierr != 0) return;
400
+ double *c3_ptr = Vector_Data_for_Read(C3s, &c3_len, ierr);
401
+ if (*ierr != 0) return;
402
+ if (p_len < 2 || p_len != c1_len || p_len != c2_len || p_len != c3_len) {
403
+ RAISE_ERROR("Sorry: vectors for create colormap must all be os same length (with at least 2 entries)", ierr);
404
+ RETURN_NIL;
405
+ }
406
+ return c_create_colormap(p, rgb, length, p_len, p_ptr, c1_ptr, c2_ptr, c3_ptr, ierr);
407
+ }
408
+
409
+ OBJ_PTR c_get_color_from_colormap(OBJ_PTR fmkr, FM *p, OBJ_PTR color_map, double x, int *ierr)
410
+ { /* x is from 0 to 1. this returns a vector for the RGB color from the given colormap */
411
+ unsigned char *buff = (unsigned char *)(String_Ptr(color_map,ierr)), r, g, b, i;
412
+ int len = String_Len(color_map,ierr);
413
+ if (*ierr != 0) RETURN_NIL;
414
+ if (len % 3 != 0) {
415
+ RAISE_ERROR("Sorry: color_map length must be a multiple of 3 (for R G B components)", ierr);
416
+ RETURN_NIL;
417
+ }
418
+ i = 3 * ROUND(x * ((len/3)-1));
419
+ r = buff[i]; g = buff[i+1]; b = buff[i+2];
420
+ OBJ_PTR result = Array_New(3);
421
+ Array_Store(result, 0, Float_New(r/255.0), ierr);
422
+ Array_Store(result, 1, Float_New(g/255.0), ierr);
423
+ Array_Store(result, 2, Float_New(b/255.0), ierr);
424
+ if (*ierr != 0) RETURN_NIL;
425
+ return result;
426
+ }
427
+
428
+ OBJ_PTR c_convert_to_colormap(OBJ_PTR fmkr, FM* p, OBJ_PTR Rs, OBJ_PTR Gs, OBJ_PTR Bs, int *ierr)
429
+ {
430
+ /* this creates an arbitrary mapping from positions to colors given as (r,g,b) triples */
431
+ /* the colormap size is set to the length of the vectors */
432
+ /* the Rs, Gs, and Bs are VALUEs from 0 to 1 representing the intensity of the color component */
433
+ long r_len, g_len, b_len;
434
+ double *r_ptr = Vector_Data_for_Read(Rs, &r_len, ierr);
435
+ if (*ierr != 0) return;
436
+ double *g_ptr = Vector_Data_for_Read(Gs, &g_len, ierr);
437
+ if (*ierr != 0) return;
438
+ double *b_ptr = Vector_Data_for_Read(Bs, &b_len, ierr);
439
+ if (*ierr != 0) return;
440
+ if (r_len <= 0 || r_len != g_len || b_len != g_len) {
441
+ RAISE_ERROR("Sorry: vectors for convert_to_colormap must all be of same length", ierr);
442
+ RETURN_NIL;
443
+ }
444
+ int i, j, buff_len = r_len * 3;
445
+ unsigned char *buff;
446
+ buff = ALLOC_N_unsigned_char(buff_len);
447
+ for (i = 0, j = 0; j < r_len; j++) {
448
+ buff[i++] = ROUND(r_ptr[j]*255);
449
+ buff[i++] = ROUND(g_ptr[j]*255);
450
+ buff[i++] = ROUND(b_ptr[j]*255);
451
+ }
452
+ OBJ_PTR lookup = String_New((char *)buff, buff_len);
453
+ free(buff);
454
+ OBJ_PTR result = Array_New(2);
455
+ Array_Store(result, 0, Integer_New(r_len-1), ierr);
456
+ Array_Store(result, 1, lookup, ierr);
457
+ if (*ierr != 0) RETURN_NIL;
458
+ return result;
459
+ }
460
+
461
+ static void Unpack_HLS(OBJ_PTR hls, double *hp, double *lp, double *sp, int *ierr)
462
+ {
463
+ int len = Array_Len(hls,ierr);
464
+ if (*ierr != 0) return;
465
+ if (len != 3) {
466
+ RAISE_ERROR("Sorry: invalid hls array: must have 3 entries", ierr); return; }
467
+ OBJ_PTR entry = Array_Entry(hls, 0, ierr); if (*ierr != 0) return;
468
+ double h = Number_to_double(entry, ierr); if (*ierr != 0) return;
469
+ entry = Array_Entry(hls, 1, ierr); if (*ierr != 0) return;
470
+ double l = Number_to_double(entry, ierr); if (*ierr != 0) return;
471
+ entry = Array_Entry(hls, 2, ierr); if (*ierr != 0) return;
472
+ double s = Number_to_double(entry, ierr); if (*ierr != 0) return;
473
+ if (l < 0.0 || l > 1.0) { RAISE_ERROR_g("Sorry: invalid lightness (%g) for hls: must be between 0 and 1", l, ierr); return; }
474
+ if (s < 0.0 || s > 1.0) { RAISE_ERROR_g("Sorry: invalid saturation (%g) for hls: must be between 0 and 1", s, ierr); return; }
475
+ *hp = h; *lp = l; *sp = s;
476
+ }
477
+
478
+ OBJ_PTR c_hls_to_rgb(OBJ_PTR fmkr, FM *p, OBJ_PTR hls_vec, int *ierr)
479
+ {
480
+ double h, l, s, r, g, b;
481
+ Unpack_HLS(hls_vec, &h, &l, &s, ierr);
482
+ if (*ierr != 0) RETURN_NIL;
483
+ convert_hls_to_rgb(h, l, s, &r, &g, &b);
484
+ OBJ_PTR result = Array_New(3);
485
+ Array_Store(result, 0, Float_New(r), ierr);
486
+ Array_Store(result, 1, Float_New(g), ierr);
487
+ Array_Store(result, 2, Float_New(b), ierr);
488
+ return result;
489
+ }
490
+
491
+ OBJ_PTR c_rgb_to_hls(OBJ_PTR fmkr, FM *p, OBJ_PTR rgb_vec, int *ierr)
492
+ {
493
+ /* hue is given as an angle from 0 to 360 around the color wheel.
494
+ 0, 60, 120, 180, 240, and 300 are respectively red, yellow, green, cyan, blue, and magenta. */
495
+ /* lightness and saturation are given as numbers from 0 to 1 */
496
+ double h, l, s, r, g, b;
497
+ Unpack_RGB(rgb_vec, &r, &g, &b, ierr);
498
+ if (*ierr != 0) RETURN_NIL;
499
+ convert_rgb_to_hls(r, g, b, &h, &l, &s);
500
+ OBJ_PTR result = Array_New(3);
501
+ Array_Store(result, 0, Float_New(h), ierr);
502
+ Array_Store(result, 1, Float_New(l), ierr);
503
+ Array_Store(result, 2, Float_New(s), ierr);
504
+ return result;
505
+ }
506
+
507
+
508
+ void c_title_color_set(OBJ_PTR fmkr, FM *p, OBJ_PTR val, int *ierr)
509
+ {
510
+ double r, g, b;
511
+ Unpack_RGB(val, &r, &g, &b, ierr);
512
+ if (*ierr != 0) return;
513
+ p->title_color_R = r;
514
+ p->title_color_G = g;
515
+ p->title_color_B = b;
516
+ }
517
+
518
+
519
+ OBJ_PTR c_title_color_get(OBJ_PTR fmkr, FM *p, int *ierr) // value is array of [r, g, b] intensities from 0 to 1
520
+ { // r g b RG
521
+ double r, g, b;
522
+ r = p->title_color_R;
523
+ g = p->title_color_G;
524
+ b = p->title_color_B;
525
+ OBJ_PTR result = Array_New(3);
526
+ Array_Store(result, 0, Float_New(r), ierr);
527
+ Array_Store(result, 1, Float_New(g), ierr);
528
+ Array_Store(result, 2, Float_New(b), ierr);
529
+ return result;
530
+ }
531
+
532
+
533
+ void c_xlabel_color_set(OBJ_PTR fmkr, FM *p, OBJ_PTR val, int *ierr)
534
+ {
535
+ double r, g, b;
536
+ Unpack_RGB(val, &r, &g, &b, ierr);
537
+ if (*ierr != 0) return;
538
+ p->xlabel_color_R = r;
539
+ p->xlabel_color_G = g;
540
+ p->xlabel_color_B = b;
541
+ }
542
+
543
+
544
+ OBJ_PTR c_xlabel_color_get(OBJ_PTR fmkr, FM *p, int *ierr) // value is array of [r, g, b] intensities from 0 to 1
545
+ { // r g b RG
546
+ double r, g, b;
547
+ r = p->xlabel_color_R;
548
+ g = p->xlabel_color_G;
549
+ b = p->xlabel_color_B;
550
+ OBJ_PTR result = Array_New(3);
551
+ Array_Store(result, 0, Float_New(r), ierr);
552
+ Array_Store(result, 1, Float_New(g), ierr);
553
+ Array_Store(result, 2, Float_New(b), ierr);
554
+ return result;
555
+ }
556
+
557
+
558
+ void c_ylabel_color_set(OBJ_PTR fmkr, FM *p, OBJ_PTR val, int *ierr)
559
+ {
560
+ double r, g, b;
561
+ Unpack_RGB(val, &r, &g, &b, ierr);
562
+ if (*ierr != 0) return;
563
+ p->ylabel_color_R = r;
564
+ p->ylabel_color_G = g;
565
+ p->ylabel_color_B = b;
566
+ }
567
+
568
+
569
+ OBJ_PTR c_ylabel_color_get(OBJ_PTR fmkr, FM *p, int *ierr) // value is array of [r, g, b] intensities from 0 to 1
570
+ { // r g b RG
571
+ double r, g, b;
572
+ r = p->ylabel_color_R;
573
+ g = p->ylabel_color_G;
574
+ b = p->ylabel_color_B;
575
+ OBJ_PTR result = Array_New(3);
576
+ Array_Store(result, 0, Float_New(r), ierr);
577
+ Array_Store(result, 1, Float_New(g), ierr);
578
+ Array_Store(result, 2, Float_New(b), ierr);
579
+ return result;
580
+ }
581
+
582
+
583
+ void c_xaxis_stroke_color_set(OBJ_PTR fmkr, FM *p, OBJ_PTR val, int *ierr)
584
+ {
585
+ double r, g, b;
586
+ Unpack_RGB(val, &r, &g, &b, ierr);
587
+ if (*ierr != 0) return;
588
+ p->xaxis_stroke_color_R = r;
589
+ p->xaxis_stroke_color_G = g;
590
+ p->xaxis_stroke_color_B = b;
591
+ }
592
+
593
+ OBJ_PTR c_xaxis_stroke_color_get(OBJ_PTR fmkr, FM *p, int *ierr) // value is array of [r, g, b] intensities from 0 to 1
594
+ { // r g b RG
595
+ double r, g, b;
596
+ r = p->xaxis_stroke_color_R;
597
+ g = p->xaxis_stroke_color_G;
598
+ b = p->xaxis_stroke_color_B;
599
+ OBJ_PTR result = Array_New(3);
600
+ Array_Store(result, 0, Float_New(r), ierr);
601
+ Array_Store(result, 1, Float_New(g), ierr);
602
+ Array_Store(result, 2, Float_New(b), ierr);
603
+ return result;
604
+ }
605
+
606
+ void c_yaxis_stroke_color_set(OBJ_PTR fmkr, FM *p, OBJ_PTR val, int *ierr)
607
+ {
608
+ double r, g, b;
609
+ Unpack_RGB(val, &r, &g, &b, ierr);
610
+ if (*ierr != 0) return;
611
+ p->yaxis_stroke_color_R = r;
612
+ p->yaxis_stroke_color_G = g;
613
+ p->yaxis_stroke_color_B = b;
614
+ }
615
+
616
+
617
+ OBJ_PTR c_yaxis_stroke_color_get(OBJ_PTR fmkr, FM *p, int *ierr) // value is array of [r, g, b] intensities from 0 to 1
618
+ { // r g b RG
619
+ double r, g, b;
620
+ r = p->yaxis_stroke_color_R;
621
+ g = p->yaxis_stroke_color_G;
622
+ b = p->yaxis_stroke_color_B;
623
+ OBJ_PTR result = Array_New(3);
624
+ Array_Store(result, 0, Float_New(r), ierr);
625
+ Array_Store(result, 1, Float_New(g), ierr);
626
+ Array_Store(result, 2, Float_New(b), ierr);
627
+ return result;
628
+ }