tioga 1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/Tioga_README +372 -0
  2. data/lgpl.txt +504 -0
  3. data/split/Dtable/defs.h +33 -0
  4. data/split/Dtable/dtable.c +1928 -0
  5. data/split/Dtable/dtable_intern.h +144 -0
  6. data/split/Dtable/dvector.h +61 -0
  7. data/split/Dtable/extconf.rb +4 -0
  8. data/split/Dtable/include/dtable.h +35 -0
  9. data/split/Dtable/lib/Dtable_extras.rb +90 -0
  10. data/split/Dtable/namespace.h +47 -0
  11. data/split/Dtable/safe_double.h +104 -0
  12. data/split/Dtable/symbols.c +92 -0
  13. data/split/Dtable/symbols.h +52 -0
  14. data/split/Dvector/defs.h +33 -0
  15. data/split/Dvector/dvector.c +5486 -0
  16. data/split/Dvector/dvector_intern.h +142 -0
  17. data/split/Dvector/extconf.rb +4 -0
  18. data/split/Dvector/include/dvector.h +61 -0
  19. data/split/Dvector/lib/Dvector_extras.rb +328 -0
  20. data/split/Dvector/lib/Numeric_extras.rb +134 -0
  21. data/split/Dvector/namespace.h +47 -0
  22. data/split/Dvector/safe_double.h +104 -0
  23. data/split/Dvector/symbols.c +92 -0
  24. data/split/Dvector/symbols.h +52 -0
  25. data/split/Flate/defs.h +33 -0
  26. data/split/Flate/extconf.rb +19 -0
  27. data/split/Flate/flate.c +156 -0
  28. data/split/Flate/flate_intern.h +97 -0
  29. data/split/Flate/include/flate.h +98 -0
  30. data/split/Flate/namespace.h +47 -0
  31. data/split/Flate/safe_double.h +104 -0
  32. data/split/Flate/symbols.c +92 -0
  33. data/split/Flate/symbols.h +52 -0
  34. data/split/Function/defs.h +33 -0
  35. data/split/Function/dvector.h +61 -0
  36. data/split/Function/extconf.rb +4 -0
  37. data/split/Function/function.c +988 -0
  38. data/split/Function/joint_qsort.c +258 -0
  39. data/split/Function/lib/Function_extras.rb +44 -0
  40. data/split/Function/namespace.h +47 -0
  41. data/split/Function/safe_double.h +104 -0
  42. data/split/Function/symbols.c +92 -0
  43. data/split/Function/symbols.h +52 -0
  44. data/split/Tioga/axes.c +774 -0
  45. data/split/Tioga/defs.h +33 -0
  46. data/split/Tioga/dtable.h +35 -0
  47. data/split/Tioga/dvector.h +61 -0
  48. data/split/Tioga/extconf.rb +4 -0
  49. data/split/Tioga/figures.c +672 -0
  50. data/split/Tioga/figures.h +855 -0
  51. data/split/Tioga/flate.h +98 -0
  52. data/split/Tioga/init.c +524 -0
  53. data/split/Tioga/lib/Arcs_and_Circles.rb +64 -0
  54. data/split/Tioga/lib/ColorConstants.rb +274 -0
  55. data/split/Tioga/lib/Colorbars.rb +10 -0
  56. data/split/Tioga/lib/Colormaps.rb +105 -0
  57. data/split/Tioga/lib/Coordinate_Conversions.rb +194 -0
  58. data/split/Tioga/lib/Creating_Paths.rb +94 -0
  59. data/split/Tioga/lib/Doc.rb +91 -0
  60. data/split/Tioga/lib/Executive.rb +515 -0
  61. data/split/Tioga/lib/FigMkr.rb +2224 -0
  62. data/split/Tioga/lib/FigureConstants.rb +125 -0
  63. data/split/Tioga/lib/Figures_and_Plots.rb +268 -0
  64. data/split/Tioga/lib/Images.rb +278 -0
  65. data/split/Tioga/lib/Legends.rb +190 -0
  66. data/split/Tioga/lib/MarkerConstants.rb +122 -0
  67. data/split/Tioga/lib/Markers.rb +129 -0
  68. data/split/Tioga/lib/Page_Frame_Bounds.rb +567 -0
  69. data/split/Tioga/lib/Rectangles.rb +94 -0
  70. data/split/Tioga/lib/Shading.rb +100 -0
  71. data/split/Tioga/lib/Special_Paths.rb +307 -0
  72. data/split/Tioga/lib/Strokes.rb +129 -0
  73. data/split/Tioga/lib/TeX_Text.rb +454 -0
  74. data/split/Tioga/lib/TexPreamble.rb +358 -0
  75. data/split/Tioga/lib/Titles_and_Labels.rb +306 -0
  76. data/split/Tioga/lib/Transparency.rb +89 -0
  77. data/split/Tioga/lib/Using_Paths.rb +164 -0
  78. data/split/Tioga/lib/Utils.rb +74 -0
  79. data/split/Tioga/lib/X_and_Y_Axes.rb +749 -0
  80. data/split/Tioga/lib/irb_tioga.rb +122 -0
  81. data/split/Tioga/lib/tioga.rb +1 -0
  82. data/split/Tioga/lib/tioga_ui.rb +5 -0
  83. data/split/Tioga/lib/tioga_ui_cmds.rb +793 -0
  84. data/split/Tioga/makers.c +989 -0
  85. data/split/Tioga/mk_tioga_sty.rb +53 -0
  86. data/split/Tioga/namespace.h +47 -0
  87. data/split/Tioga/pdf_font_dicts.c +18253 -0
  88. data/split/Tioga/pdfcolor.c +486 -0
  89. data/split/Tioga/pdfcoords.c +505 -0
  90. data/split/Tioga/pdffile.c +342 -0
  91. data/split/Tioga/pdfimage.c +536 -0
  92. data/split/Tioga/pdfpath.c +914 -0
  93. data/split/Tioga/pdfs.h +229 -0
  94. data/split/Tioga/pdftext.c +443 -0
  95. data/split/Tioga/safe_double.h +104 -0
  96. data/split/Tioga/symbols.c +92 -0
  97. data/split/Tioga/symbols.h +52 -0
  98. data/split/Tioga/texout.c +380 -0
  99. data/split/defs.h +33 -0
  100. data/split/extconf.rb +107 -0
  101. data/split/mkmf2.rb +1612 -0
  102. data/split/namespace.h +47 -0
  103. data/split/safe_double.h +104 -0
  104. data/split/scripts/tioga +4 -0
  105. data/split/symbols.c +92 -0
  106. data/split/symbols.h +52 -0
  107. data/tests/dtable_test.data +6 -0
  108. data/tests/dvector_read_test.data +1 -0
  109. data/tests/dvector_test.data +101 -0
  110. data/tests/tc_Dtable.rb +221 -0
  111. data/tests/tc_Dvector.rb +791 -0
  112. data/tests/tc_FMkr.rb +162 -0
  113. data/tests/tc_Flate.rb +45 -0
  114. data/tests/tc_Function.rb +111 -0
  115. data/tests/ts_Tioga.rb +38 -0
  116. metadata +163 -0
@@ -0,0 +1,486 @@
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)
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
+ rb_raise(rb_eArgError, "Error writing function sample data");
49
+ fprintf(OF, "\nendstream\nendobj\n");
50
+ }
51
+
52
+ void Write_Functions(void)
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);
58
+ }
59
+ }
60
+
61
+ static int create_function(int hival, int lookup_len, unsigned char *lookup)
62
+ {
63
+ Function_Info *fo = ALLOC(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, unsigned char, 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 = ALLOC(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
+ VALUE FM_stroke_opacity_set(VALUE fmkr, VALUE value)
100
+ { // /GSi gs for ExtGState obj with /CS set to stroke opacity value
101
+ FM *p = Get_FM(fmkr);
102
+ if (constructing_path) rb_raise(rb_eArgError, "Sorry: must not be constructing a path when change stroke opacity");
103
+ value = rb_Float(value);
104
+ double stroke_opacity = NUM2DBL(value);
105
+ if (stroke_opacity == p->stroke_opacity) return value;
106
+ int gs_num = Get_Stroke_Opacity_XGS(stroke_opacity);
107
+ fprintf(TF, "/GS%i gs\n", gs_num);
108
+ p->stroke_opacity = stroke_opacity;
109
+ return value;
110
+ }
111
+
112
+ void Free_Fill_Opacities(void)
113
+ {
114
+ Fill_Opacity_State *p;
115
+ while (fill_opacities != NULL) {
116
+ p = fill_opacities; fill_opacities = p->next; free(p);
117
+ }
118
+ }
119
+
120
+ static int Get_Fill_Opacity_XGS(double fill_opacity)
121
+ {
122
+ Fill_Opacity_State *p;
123
+ for (p = fill_opacities; p != NULL; p = p->next) {
124
+ if (p->fill_opacity == fill_opacity) return p->gs_num;
125
+ }
126
+ p = ALLOC(Fill_Opacity_State);
127
+ p->fill_opacity = fill_opacity;
128
+ p->gs_num = next_available_gs_number++;
129
+ p->obj_num = next_available_object_number++;
130
+ p->next = fill_opacities;
131
+ fill_opacities = p;
132
+ return p->gs_num;
133
+ }
134
+
135
+ VALUE FM_fill_opacity_set(VALUE fmkr, VALUE value)
136
+ { // /GSi gs for ExtGState obj with /cs set to fill opacity value
137
+ FM *p = Get_FM(fmkr);
138
+ if (constructing_path) rb_raise(rb_eArgError, "Sorry: must not be constructing a path when change fill opacity");
139
+ value = rb_Float(value);
140
+ double fill_opacity = NUM2DBL(value);
141
+ if (fill_opacity == p->fill_opacity) return value;
142
+ int gs_num = Get_Fill_Opacity_XGS(fill_opacity);
143
+ fprintf(TF, "/GS%i gs\n", gs_num);
144
+ p->fill_opacity = fill_opacity;
145
+ return value;
146
+ }
147
+
148
+ void Write_Stroke_Opacity_Objects(void)
149
+ {
150
+ Stroke_Opacity_State *p;
151
+ for (p = stroke_opacities; p != NULL; p = p->next) {
152
+ Record_Object_Offset(p->obj_num);
153
+ fprintf(OF, "%2i 0 obj << /Type /ExtGState /CA %g >> endobj\n", p->obj_num, p->stroke_opacity);
154
+ }
155
+ }
156
+
157
+ void Write_Fill_Opacity_Objects(void)
158
+ {
159
+ Fill_Opacity_State *p;
160
+ for (p = fill_opacities; p != NULL; p = p->next) {
161
+ Record_Object_Offset(p->obj_num);
162
+ fprintf(OF, "%2i 0 obj << /Type /ExtGState /ca %g >> endobj\n", p->obj_num, p->fill_opacity);
163
+ }
164
+ }
165
+
166
+ /* Shading */
167
+
168
+ void Free_Shadings()
169
+ {
170
+ Shading_Info *so;
171
+ while (shades_list != NULL) {
172
+ so = shades_list;
173
+ shades_list = so->next;
174
+ free(so);
175
+ }
176
+ }
177
+
178
+ void Write_Shadings(void)
179
+ {
180
+ Shading_Info *so;
181
+ for (so = shades_list; so != NULL; so = so->next) {
182
+ Record_Object_Offset(so->obj_num);
183
+ fprintf(OF, "%i 0 obj <<\n", so->obj_num);
184
+ if (so->axial) {
185
+ fprintf(OF, "\t/ShadingType 2\n\t/Coords [%0.2f %0.2f %0.2f %0.2f]\n",
186
+ so->x0, so->y0, so->x1, so->y1);
187
+ } else {
188
+ fprintf(OF, "\t/ShadingType 3\n\t/Coords [%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f]\n",
189
+ so->x0, so->y0, so->r0, so->x1, so->y1, so->r1);
190
+ }
191
+ if (so->extend_start || so->extend_end) fprintf(OF, "\t/Extend [ %s %s ]\n",
192
+ (so->extend_start)? "true" : "false", (so->extend_end)? "true" : "false");
193
+ fprintf(OF, "\t/ColorSpace /DeviceRGB\n");
194
+ fprintf(OF, "\t/Function %i 0 R\n", so->function);
195
+ fprintf(OF, ">> endobj\n");
196
+ }
197
+ }
198
+
199
+
200
+ void c_axial_shading(FM *p, double x0, double y0, double x1, double y1,
201
+ int hival, int lookup_len, unsigned char *lookup, bool extend_start, bool extend_end)
202
+ {
203
+ Shading_Info *so = ALLOC(Shading_Info);
204
+ so->next = shades_list;
205
+ shades_list = so;
206
+ so->shade_num = next_available_shade_number++;
207
+ so->obj_num = next_available_object_number++;
208
+ so->function = create_function(hival, lookup_len, lookup);
209
+ so->axial = true;
210
+ so->x0 = x0;
211
+ so->y0 = y0;
212
+ so->x1 = x1;
213
+ so->y1 = y1;
214
+ so->extend_start = extend_start;
215
+ so->extend_end = extend_end;
216
+ fprintf(TF, "/Shade%i sh\n", so->shade_num);
217
+ }
218
+
219
+ VALUE FM_private_axial_shading(VALUE fmkr, VALUE x0, VALUE y0, VALUE x1, VALUE y1,
220
+ VALUE colormap, VALUE extend_start, VALUE extend_end)
221
+ {
222
+ FM *p = Get_FM(fmkr);
223
+ x0 = rb_Float(x0);
224
+ y0 = rb_Float(y0);
225
+ x1 = rb_Float(x1);
226
+ y1 = rb_Float(y1);
227
+ colormap = rb_Array(colormap);
228
+ if (RARRAY(colormap)->len != 2)
229
+ rb_raise(rb_eArgError, "Sorry: colormap must be array [hivalue, lookup]");
230
+ VALUE hival = rb_ary_entry(colormap, 0);
231
+ hival = rb_Integer(hival);
232
+ VALUE lookup = rb_ary_entry(colormap, 1);
233
+ lookup = rb_String(lookup);
234
+ c_axial_shading(p, convert_figure_to_output_x(p,NUM2DBL(x0)), convert_figure_to_output_y(p,NUM2DBL(y0)),
235
+ convert_figure_to_output_x(p,NUM2DBL(x1)), convert_figure_to_output_y(p,NUM2DBL(y1)),
236
+ NUM2INT(hival), RSTRING(lookup)->len, (unsigned char *)(RSTRING(lookup)->ptr),
237
+ extend_start == Qtrue, extend_end == Qtrue);
238
+ return fmkr;
239
+ }
240
+
241
+ void c_radial_shading(FM *p, double x0, double y0, double r0, double x1, double y1, double r1,
242
+ int hival, int lookup_len, unsigned char *lookup,
243
+ double a, double b, double c, double d, double e, double f, bool extend_start, bool extend_end)
244
+ {
245
+ Shading_Info *so = ALLOC(Shading_Info);
246
+ so->next = shades_list;
247
+ shades_list = so;
248
+ so->shade_num = next_available_shade_number++;
249
+ so->obj_num = next_available_object_number++;
250
+ so->function = create_function(hival, lookup_len, lookup);
251
+ so->axial = false;
252
+ so->x0 = x0;
253
+ so->y0 = y0;
254
+ so->r0 = r0;
255
+ so->x1 = x1;
256
+ so->y1 = y1;
257
+ so->r1 = r1;
258
+ so->extend_start = extend_start;
259
+ so->extend_end = extend_end;
260
+ if (a != 1.0 || b != 0.0 || c != 0.0 || d != 1.0 || e != 0 || f != 0) {
261
+ fprintf(TF, "q %0.2f %0.2f %0.2f %0.2f %0.2f %0.2f cm /Shade%i sh Q\n",
262
+ a, b, c, d, e, f, so->shade_num);
263
+ } else {
264
+ fprintf(TF, "/Shade%i sh\n", so->shade_num);
265
+ }
266
+ }
267
+
268
+ VALUE FM_private_radial_shading(VALUE fmkr,
269
+ VALUE x0, VALUE y0, VALUE r0,
270
+ VALUE x1, VALUE y1, VALUE r1, VALUE colormap,
271
+ VALUE a, VALUE b, VALUE c, VALUE d, VALUE extend_start, VALUE extend_end)
272
+ {
273
+ FM *p = Get_FM(fmkr);
274
+ x0 = rb_Float(x0);
275
+ y0 = rb_Float(y0);
276
+ r0 = rb_Float(r0);
277
+ x1 = rb_Float(x1);
278
+ y1 = rb_Float(y1);
279
+ r1 = rb_Float(r1);
280
+ a = rb_Float(a);
281
+ b = rb_Float(b);
282
+ c = rb_Float(c);
283
+ d = rb_Float(d);
284
+ colormap = rb_Array(colormap);
285
+ if (RARRAY(colormap)->len != 2)
286
+ rb_raise(rb_eArgError, "Sorry: colormap must be array [hivalue, lookup]");
287
+ VALUE hival = rb_ary_entry(colormap, 0);
288
+ hival = rb_Integer(hival);
289
+ VALUE lookup = rb_ary_entry(colormap, 1);
290
+ lookup = rb_String(lookup);
291
+ c_radial_shading(p,
292
+ NUM2DBL(x0), NUM2DBL(y0), NUM2DBL(r0),
293
+ NUM2DBL(x1), NUM2DBL(y1), NUM2DBL(r1),
294
+ NUM2INT(hival), RSTRING(lookup)->len, (unsigned char *)(RSTRING(lookup)->ptr),
295
+ convert_figure_to_output_dx(p,NUM2DBL(a)), convert_figure_to_output_dy(p,NUM2DBL(b)),
296
+ convert_figure_to_output_dx(p,NUM2DBL(c)), convert_figure_to_output_dy(p,NUM2DBL(d)),
297
+ convert_figure_to_output_x(p,0.0), convert_figure_to_output_y(p,0.0),
298
+ extend_start == Qtrue, extend_end == Qtrue);
299
+ return fmkr;
300
+ }
301
+
302
+ /* Colormaps
303
+ */
304
+
305
+ VALUE c_create_colormap(FM *p, bool rgb_flag, int length,
306
+ int num_pts, double *ps, double *c1s, double *c2s, double *c3s)
307
+ {
308
+ int i;
309
+ if (ps[0] != 0.0 || ps[num_pts-1] != 1.0)
310
+ rb_raise(rb_eArgError, "Sorry: first control point for create colormap must be at 0.0 and last must be at 1.0");
311
+ for (i = 1; i < num_pts; i++) {
312
+ if (ps[i-1] > ps[i])
313
+ rb_raise(rb_eArgError, "Sorry: control points for create colormap must be increasing from 0 to 1");
314
+ }
315
+ int j, buff_len = length * 3, hival = length-1;
316
+ unsigned char *buff;
317
+ buff = ALLOC_N(unsigned char, buff_len);
318
+ for (j = 0, i = 0; j < length; j++) {
319
+ double x = j; x /= (length-1);
320
+ double c1, c2, c3, r, g, b;
321
+ c1 = c_dvector_linear_interpolate(num_pts, ps, c1s, x);
322
+ c2 = c_dvector_linear_interpolate(num_pts, ps, c2s, x);
323
+ c3 = c_dvector_linear_interpolate(num_pts, ps, c3s, x);
324
+ if (rgb_flag) { r = c1; g = c2; b = c3; }
325
+ else c_hls_to_rgb(c1, c2, c3, &r, &g, &b);
326
+ buff[i++] = ROUND(hival * r);
327
+ buff[i++] = ROUND(hival * g);
328
+ buff[i++] = ROUND(hival * b);
329
+ }
330
+ VALUE lookup = rb_str_new((char *)buff, buff_len);
331
+ free(buff);
332
+ VALUE result = rb_ary_new2(2);
333
+ rb_ary_store(result, 0, INT2FIX(hival));
334
+ rb_ary_store(result, 1, lookup);
335
+ return result;
336
+ }
337
+
338
+ VALUE FM_private_create_colormap(VALUE fmkr, VALUE rgb_flag,
339
+ VALUE length, VALUE Ps, VALUE C1s, VALUE C2s, VALUE C3s)
340
+ {
341
+ FM *p = Get_FM(fmkr);
342
+ bool rgb = rgb_flag != Qfalse;
343
+ length = rb_Integer(length);
344
+ long p_len, c1_len, c2_len, c3_len;
345
+ double *p_ptr = Dvector_Data_for_Read(Ps, &p_len);
346
+ double *c1_ptr = Dvector_Data_for_Read(C1s, &c1_len);
347
+ double *c2_ptr = Dvector_Data_for_Read(C2s, &c2_len);
348
+ double *c3_ptr = Dvector_Data_for_Read(C3s, &c3_len);
349
+ if (p_len < 2 || p_len != c1_len || p_len != c2_len || p_len != c3_len)
350
+ rb_raise(rb_eArgError, "Sorry: vectors for create colormap must all be os same length (with at least 2 entries)");
351
+ return c_create_colormap(p, rgb, NUM2INT(length), p_len, p_ptr, c1_ptr, c2_ptr, c3_ptr);
352
+ }
353
+
354
+ VALUE FM_get_color_from_colormap(VALUE fmkr, VALUE color_map, VALUE color_position)
355
+ {
356
+ color_position = rb_Float(color_position);
357
+ double x = NUM2DBL(color_position);
358
+ color_map = rb_String(color_map);
359
+ unsigned char *buff = (unsigned char *)(RSTRING(color_map)->ptr), r, g, b, i;
360
+ int len = RSTRING(color_map)->len;
361
+ if (len % 3 != 0) rb_raise(rb_eArgError, "Sorry: color_map length must be a multiple of 3 (for R G B components)");
362
+ i = 3 * ROUND(x * ((len/3)-1));
363
+ r = buff[i]; g = buff[i+1]; b = buff[i+2];
364
+ VALUE result = rb_ary_new2(3);
365
+ rb_ary_store(result, 0, rb_float_new(r/255.0));
366
+ rb_ary_store(result, 1, rb_float_new(g/255.0));
367
+ rb_ary_store(result, 2, rb_float_new(b/255.0));
368
+ return result;
369
+ fmkr = Qnil;
370
+ }
371
+
372
+ VALUE FM_convert_to_colormap(VALUE fmkr, VALUE Rs, VALUE Gs, VALUE Bs)
373
+ {
374
+ long r_len, g_len, b_len;
375
+ double *r_ptr = Dvector_Data_for_Read(Rs, &r_len);
376
+ double *g_ptr = Dvector_Data_for_Read(Gs, &g_len);
377
+ double *b_ptr = Dvector_Data_for_Read(Bs, &b_len);
378
+ if (r_len <= 0 || r_len != g_len || b_len != g_len)
379
+ rb_raise(rb_eArgError, "Sorry: vectors for convert_to_colormap must all be of same length");
380
+ int i, j, buff_len = r_len * 3;
381
+ unsigned char *buff;
382
+ buff = ALLOC_N(unsigned char, buff_len);
383
+ for (i = 0, j = 0; j < r_len; j++) {
384
+ buff[i++] = ROUND(r_ptr[j]*255);
385
+ buff[i++] = ROUND(g_ptr[j]*255);
386
+ buff[i++] = ROUND(b_ptr[j]*255);
387
+ }
388
+ VALUE lookup = rb_str_new((char *)buff, buff_len);
389
+ free(buff);
390
+ VALUE result = rb_ary_new2(2);
391
+ rb_ary_store(result, 0, INT2FIX(r_len-1));
392
+ rb_ary_store(result, 1, lookup);
393
+ return result;
394
+ }
395
+
396
+ static double value(double n1, double n2, double hue) // from plplot plctrl.c
397
+ {
398
+ double val;
399
+ while (hue >= 360.) hue -= 360.;
400
+ while (hue < 0.) hue += 360.;
401
+ if (hue < 60.) val = n1 + (n2 - n1) * hue / 60.;
402
+ else if (hue < 180.) val = n2;
403
+ else if (hue < 240.) val = n1 + (n2 - n1) * (240. - hue) / 60.;
404
+ else val = n1;
405
+ return (val);
406
+ }
407
+
408
+ void c_hls_to_rgb(double h, double l, double s, double *p_r, double *p_g, double *p_b) // from plplot plctrl.c
409
+ {
410
+ double m1, m2;
411
+ if (l <= .5) m2 = l * (s + 1.);
412
+ else m2 = l + s - l * s;
413
+ m1 = 2 * l - m2;
414
+ *p_r = value(m1, m2, h + 120.);
415
+ *p_g = value(m1, m2, h);
416
+ *p_b = value(m1, m2, h - 120.);
417
+ }
418
+
419
+ void c_rgb_to_hls(double r, double g, double b, double *p_h, double *p_l, double *p_s) // from plplot plctrl.c
420
+ {
421
+ double h, l, s, d, rc, gc, bc, rgb_min, rgb_max;
422
+ rgb_min = MIN( r, MIN( g, b ));
423
+ rgb_max = MAX( r, MAX( g, b ));
424
+ l = (rgb_min+rgb_max) / 2.0;
425
+ if (rgb_min == rgb_max) s = h = 0;
426
+ else {
427
+ d = rgb_max - rgb_min;
428
+ if (l < 0.5) s = 0.5 * d / l;
429
+ else s = 0.5* d / (1.-l);
430
+ rc = (rgb_max-r) / d;
431
+ gc = (rgb_max-g) / d;
432
+ bc = (rgb_max-b) / d;
433
+ if (r == rgb_max) h = bc-gc;
434
+ else if (g == rgb_max) h = rc-bc+2;
435
+ else h = gc-rc-2;
436
+ h = h*60;
437
+ if (h < 0) h = h+360;
438
+ else if (h >= 360) h = h-360;
439
+ }
440
+ *p_h = h;
441
+ *p_l = l;
442
+ *p_s = s;
443
+ }
444
+
445
+ static void Unpack_HLS(VALUE hls, double *hp, double *lp, double *sp)
446
+ {
447
+ hls = rb_Array(hls);
448
+ if (RARRAY(hls)->len != 3) rb_raise(rb_eArgError, "Sorry: invalid hls array: must have 3 entries");
449
+ VALUE entry = rb_ary_entry(hls, 0);
450
+ entry = rb_Float(entry);
451
+ double h = NUM2DBL(entry);
452
+ entry = rb_ary_entry(hls, 1);
453
+ entry = rb_Float(entry);
454
+ double l = NUM2DBL(entry);
455
+ entry = rb_ary_entry(hls, 2);
456
+ entry = rb_Float(entry);
457
+ double s = NUM2DBL(entry);
458
+ if (l < 0.0 || l > 1.0) rb_raise(rb_eArgError, "Sorry: invalid lightness (%g) for hls: must be between 0 and 1", l);
459
+ if (s < 0.0 || s > 1.0) rb_raise(rb_eArgError, "Sorry: invalid saturation (%g) for hls: must be between 0 and 1", s);
460
+ *hp = h; *lp = l; *sp = s;
461
+ }
462
+
463
+ VALUE FM_hls_to_rgb(VALUE fmkr, VALUE hls_vec)
464
+ {
465
+ double h, l, s, r, g, b;
466
+ Unpack_HLS(hls_vec, &h, &l, &s);
467
+ c_hls_to_rgb(h, l, s, &r, &g, &b);
468
+ VALUE result = rb_ary_new2(3);
469
+ rb_ary_store(result, 0, rb_float_new(r));
470
+ rb_ary_store(result, 1, rb_float_new(g));
471
+ rb_ary_store(result, 2, rb_float_new(b));
472
+ return result;
473
+ }
474
+
475
+ VALUE FM_rgb_to_hls(VALUE fmkr, VALUE rgb_vec)
476
+ {
477
+ double h, l, s, r, g, b;
478
+ Unpack_RGB(rgb_vec, &r, &g, &b);
479
+ c_rgb_to_hls(r, g, b, &h, &l, &s);
480
+ VALUE result = rb_ary_new2(3);
481
+ rb_ary_store(result, 0, rb_float_new(h));
482
+ rb_ary_store(result, 1, rb_float_new(l));
483
+ rb_ary_store(result, 2, rb_float_new(s));
484
+ return result;
485
+ }
486
+