tioga 1.8 → 1.9

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 (53) hide show
  1. data/Tioga_README +46 -11
  2. data/split/Dtable/dtable.c +2 -2
  3. data/split/Dtable/dvector.h +8 -0
  4. data/split/Dtable/namespace.h +16 -8
  5. data/split/Dtable/symbols.h +1 -1
  6. data/split/Dvector/dvector.c +77 -2
  7. data/split/Dvector/dvector_intern.h +2 -0
  8. data/split/Dvector/include/dvector.h +8 -0
  9. data/split/Dvector/lib/Dvector_extras.rb +12 -0
  10. data/split/Dvector/namespace.h +16 -8
  11. data/split/Dvector/symbols.h +1 -1
  12. data/split/Flate/namespace.h +16 -8
  13. data/split/Flate/symbols.h +1 -1
  14. data/split/Function/dvector.h +8 -0
  15. data/split/Function/function.c +2 -1
  16. data/split/Function/namespace.h +16 -8
  17. data/split/Function/symbols.h +1 -1
  18. data/split/Tioga/axes.c +217 -75
  19. data/split/Tioga/dvector.h +8 -0
  20. data/split/Tioga/figures.c +19 -2
  21. data/split/Tioga/figures.h +7 -6
  22. data/split/Tioga/generic.c +14 -1
  23. data/split/Tioga/generic.h +13 -0
  24. data/split/Tioga/init.c +5 -9
  25. data/split/Tioga/lib/Colormaps.rb +33 -2
  26. data/split/Tioga/lib/Doc.rb +30 -0
  27. data/split/Tioga/lib/Executive.rb +4 -2
  28. data/split/Tioga/lib/FigMkr.rb +219 -53
  29. data/split/Tioga/lib/Figures_and_Plots.rb +7 -0
  30. data/split/Tioga/lib/Images.rb +10 -2
  31. data/split/Tioga/lib/Legends.rb +7 -3
  32. data/split/Tioga/lib/Markers.rb +7 -0
  33. data/split/Tioga/lib/TexPreamble.rb +56 -56
  34. data/split/Tioga/lib/Utils.rb +7 -0
  35. data/split/Tioga/lib/maker.rb +1 -0
  36. data/split/Tioga/lib/tioga_ui_cmds.rb +6 -5
  37. data/split/Tioga/namespace.h +16 -8
  38. data/split/Tioga/pdfcolor.c +63 -7
  39. data/split/Tioga/pdfcoords.c +0 -16
  40. data/split/Tioga/pdfimage.c +16 -2
  41. data/split/Tioga/pdfs.h +1 -0
  42. data/split/Tioga/pdftext.c +223 -82
  43. data/split/Tioga/symbols.h +1 -1
  44. data/split/Tioga/texout.c +1 -1
  45. data/split/Tioga/wrappers.c +21 -10
  46. data/split/Tioga/wrappers.h +5 -0
  47. data/split/extconf.rb +27 -15
  48. data/split/namespace.h +16 -8
  49. data/split/scripts/tioga +0 -0
  50. data/split/symbols.h +1 -1
  51. data/tests/Icon_Test.pdf +0 -0
  52. data/tests/tc_Dvector.rb +24 -0
  53. metadata +38 -37
@@ -31,6 +31,13 @@
31
31
 
32
32
  /* functions for handling Dvectors: */
33
33
 
34
+ DECLARE_SYMBOL(bool, isa_Dvector, (VALUE obj));
35
+ /* returns true if the obj is a Dvector */
36
+ DECLARE_SYMBOL(long, len_Dvector, (VALUE dvector));
37
+ /* returns length of the dvector */
38
+ DECLARE_SYMBOL(double, access_Dvector, (VALUE dvector, long idx));
39
+ /* returns the value of entry idx in dvector */
40
+
34
41
  DECLARE_SYMBOL(double *, Dvector_Data_for_Read, (VALUE dvector, long *len_ptr));
35
42
  /* returns pointer to the dvector's data (which may be shared) */
36
43
  DECLARE_SYMBOL(double *, Dvector_Data_Copy, (VALUE dvector, long *len_ptr));
@@ -46,6 +53,7 @@ DECLARE_SYMBOL(void, Dvector_Store_Double, (VALUE ary, long idx, double val));
46
53
  /* pushes one element onto the vector */
47
54
  DECLARE_SYMBOL(void, Dvector_Push_Double, (VALUE ary, double val));
48
55
 
56
+
49
57
  /* functions for interpolation */
50
58
  DECLARE_SYMBOL(double, c_dvector_spline_interpolate,
51
59
  (double x, int n_pts_data, double *Xs, double *Ys,
@@ -230,6 +230,10 @@ FM *Get_FM(OBJ_PTR fmkr, int *ierr) {
230
230
  RO_BOOL_ATTR(left_edge_visible)
231
231
  INT_ATTR(right_edge_type)
232
232
  RO_BOOL_ATTR(right_edge_visible)
233
+
234
+ /* Major ticks picking algorithm */
235
+ BOOL_ATTR(vincent_or_bill)
236
+
233
237
 
234
238
  /* Legend */
235
239
  DBL_ATTR(legend_text_width)
@@ -382,6 +386,8 @@ void Init_FigureMaker(void) {
382
386
  /* colors */
383
387
  rb_define_method(cFM, "hls_to_rgb", FM_hls_to_rgb, 1);
384
388
  rb_define_method(cFM, "rgb_to_hls", FM_rgb_to_hls, 1);
389
+ rb_define_method(cFM, "string_hls_to_rgb!", FM_string_hls_to_rgb_bang, 1);
390
+ rb_define_method(cFM, "string_rgb_to_hls!", FM_string_rgb_to_hls_bang, 1);
385
391
  /* coordinate system conversions */
386
392
  rb_define_method(cFM, "convert_inches_to_output", FM_convert_inches_to_output, 1);
387
393
  rb_define_method(cFM, "convert_output_to_inches", FM_convert_output_to_inches, 1);
@@ -487,12 +493,13 @@ void Init_FigureMaker(void) {
487
493
  rb_define_method(cFM, "private_radial_shading", FM_private_radial_shading, 13);
488
494
  /* markers */
489
495
  rb_define_method(cFM, "register_font", FM_register_font, 1);
490
- rb_define_method(cFM, "private_show_marker", FM_private_show_marker, 15);
496
+ rb_define_method(cFM, "private_show_marker", FM_private_show_marker, 1);
491
497
  rb_define_method(cFM, "marker_string_info", FM_marker_string_info, 3);
492
498
  /* images */
493
499
  rb_define_method(cFM, "private_show_jpg", FM_private_show_jpg, 5);
494
500
  rb_define_method(cFM, "private_show_rgb_image", FM_private_show_rgb_image, 11);
495
- rb_define_method(cFM, "private_show_cmyk_image", FM_private_show_rgb_image, 11);
501
+ rb_define_method(cFM, "private_show_hls_image", FM_private_show_hls_image, 11);
502
+ rb_define_method(cFM, "private_show_cmyk_image", FM_private_show_cmyk_image, 11);
496
503
  rb_define_method(cFM, "private_show_grayscale_image", FM_private_show_grayscale_image, 11);
497
504
  rb_define_method(cFM, "private_show_monochrome_image", FM_private_show_monochrome_image, 12);
498
505
  rb_define_method(cFM, "private_show_image", FM_private_show_image, 15);
@@ -617,6 +624,10 @@ void Init_FigureMaker(void) {
617
624
  attr_reader(left_edge_visible)
618
625
  attr_accessors(right_edge_type)
619
626
  attr_reader(right_edge_visible)
627
+
628
+
629
+ /* Major ticks algorithm */
630
+ attr_accessors(vincent_or_bill)
620
631
 
621
632
  /* Legend */
622
633
  attr_accessors(legend_text_width)
@@ -644,6 +655,9 @@ void Init_FigureMaker(void) {
644
655
  RB_IMPORT_SYMBOL(cDvector, Dvector_Create);
645
656
  RB_IMPORT_SYMBOL(cDvector, Dvector_Data_Resize);
646
657
  RB_IMPORT_SYMBOL(cDvector, Dvector_Data_Replace);
658
+ RB_IMPORT_SYMBOL(cDvector, isa_Dvector);
659
+ RB_IMPORT_SYMBOL(cDvector, len_Dvector);
660
+ RB_IMPORT_SYMBOL(cDvector, access_Dvector);
647
661
  RB_IMPORT_SYMBOL(cDvector, Dvector_Data_for_Read);
648
662
  RB_IMPORT_SYMBOL(cDvector, Dvector_Data_for_Write);
649
663
  RB_IMPORT_SYMBOL(cDvector, Dvector_Store_Double);
@@ -665,6 +679,9 @@ void Init_FigureMaker(void) {
665
679
  IMPLEMENT_SYMBOL(Dvector_Create);
666
680
  IMPLEMENT_SYMBOL(Dvector_Data_Resize);
667
681
  IMPLEMENT_SYMBOL(Dvector_Data_Replace);
682
+ IMPLEMENT_SYMBOL(isa_Dvector);
683
+ IMPLEMENT_SYMBOL(len_Dvector);
684
+ IMPLEMENT_SYMBOL(access_Dvector);
668
685
  IMPLEMENT_SYMBOL(Dvector_Data_for_Read);
669
686
  IMPLEMENT_SYMBOL(Dvector_Data_for_Write);
670
687
  IMPLEMENT_SYMBOL(Dvector_Store_Double);
@@ -281,7 +281,10 @@ typedef struct {
281
281
  bool left_edge_visible;
282
282
  int right_edge_type;
283
283
  bool right_edge_visible;
284
-
284
+
285
+ /* General axis stuff*/
286
+ bool vincent_or_bill;
287
+
285
288
  /* Legend */
286
289
  // units are text heights for x and y for locations and sizes
287
290
  double legend_line_x0; // x location of start of line
@@ -454,6 +457,8 @@ extern void c_xaxis_stroke_color_set(OBJ_PTR fmkr, FM *p, OBJ_PTR valc_hls_to_rg
454
457
  extern OBJ_PTR c_xaxis_stroke_color_get(OBJ_PTR fmkr, FM *pc_hls_to_rgb, int *ierr); // value is array of [r, g, b] intensities from 0 to 1
455
458
  extern void c_yaxis_stroke_color_set(OBJ_PTR fmkr, FM *p, OBJ_PTR valc_hls_to_rgb, int *ierr);
456
459
  extern OBJ_PTR c_yaxis_stroke_color_get(OBJ_PTR fmkr, FM *pc_hls_to_rgb, int *ierr); // value is array of [r, g, b] intensities from 0 to 1
460
+ extern void c_string_hls_to_rgb_bang(OBJ_PTR fmkr, FM *p, unsigned char* hls_str, long len, int *ierr);
461
+ extern void c_string_rgb_to_hls_bang(OBJ_PTR fmkr, FM *p, unsigned char* rgb_str, long len, int *ierr);
457
462
 
458
463
  /*======================================================================*/
459
464
  // pdfcoords.c
@@ -643,11 +648,7 @@ extern void Write_Font_Widths(void);
643
648
 
644
649
  extern OBJ_PTR c_register_font(OBJ_PTR fmkr, FM *p, char *font_name, int *ierr);
645
650
  extern OBJ_PTR c_marker_string_info(OBJ_PTR fmkr, FM *p, int fnt, unsigned char *text, double scale, int *ierr);
646
- extern void c_private_show_marker(
647
- OBJ_PTR fmkr, FM *p, int int_args, OBJ_PTR stroke_width, OBJ_PTR string,
648
- OBJ_PTR x, OBJ_PTR y, OBJ_PTR x_vec, OBJ_PTR y_vec,
649
- double h_scale, double v_scale, double scale, double it_angle, double ascent_angle, double angle,
650
- OBJ_PTR fill_color, OBJ_PTR stroke_color, int *ierr);
651
+ extern void c_private_show_marker(OBJ_PTR fmkr, FM *p, OBJ_PTR args, int *ierr);
651
652
 
652
653
  /*======================================================================*/
653
654
  // texout.c
@@ -20,6 +20,7 @@
20
20
  */
21
21
 
22
22
  #include <ctype.h>
23
+
23
24
  #include "dvector.h"
24
25
  #include "dtable.h"
25
26
  #include "ruby.h"
@@ -30,6 +31,7 @@
30
31
  #include "flate.h"
31
32
 
32
33
 
34
+
33
35
  static OBJ_PTR rb_Integer_class, rb_Numeric_class;
34
36
 
35
37
  void Init_generic(void) {
@@ -73,7 +75,8 @@ char *CString_Ptr(OBJ_PTR obj, int *ierr) {
73
75
 
74
76
  OBJ_PTR Array_New(long len) { return rb_ary_new2(len); }
75
77
 
76
- long Array_Len(OBJ_PTR obj, int *ierr) { return (RARRAY(rb_Array(obj))->len); }
78
+ long Array_Len(OBJ_PTR obj, int *ierr) {
79
+ return isa_Dvector(obj)? len_Dvector(obj) : (RARRAY(rb_Array(obj))->len); }
77
80
 
78
81
  OBJ_PTR Array_Entry(OBJ_PTR obj, long indx, int *ierr) { return rb_ary_entry(obj,indx); }
79
82
 
@@ -81,6 +84,16 @@ void Array_Store(OBJ_PTR obj, long indx, OBJ_PTR val, int *ierr) { rb_ary_store(
81
84
 
82
85
  void Array_Push(OBJ_PTR obj, OBJ_PTR val, int *ierr) { rb_ary_push(obj,val); }
83
86
 
87
+ double Array_Entry_double(OBJ_PTR obj, long indx, int *ierr) {
88
+ return isa_Dvector(obj)? access_Dvector(obj,indx) : Number_to_double(rb_ary_entry(obj,indx),ierr);
89
+ }
90
+
91
+ long Array_Entry_int(OBJ_PTR obj, long indx, int *ierr) {
92
+ return isa_Dvector(obj)? round(access_Dvector(obj,indx)) : Number_to_int(rb_ary_entry(obj,indx),ierr);
93
+ }
94
+
95
+
96
+
84
97
  ID_PTR ID_Get(char *name) { return rb_intern(name); }
85
98
 
86
99
  char *ID_Name(ID_PTR id, int *ierr) { return rb_id2name(id); }
@@ -153,6 +153,19 @@ extern void Array_Store(OBJ_PTR obj, long indx, OBJ_PTR val, int *ierr);
153
153
  extern void Array_Push(OBJ_PTR obj, OBJ_PTR val, int *ierr);
154
154
  // pushes val onto the end of array obj.
155
155
  // raises error if obj not a kind of array
156
+
157
+
158
+ extern double Array_Entry_double(OBJ_PTR obj, long indx, int *ierr);
159
+ // returns a C double
160
+ // tries to convert obj to array if necessary
161
+ // raises error if obj not a kind of array and cannot be converted to one
162
+ // or if entry is not a number and cannot be converted to one.
163
+
164
+ extern long Array_Entry_int(OBJ_PTR obj, long indx, int *ierr);
165
+ // returns a C long int
166
+ // tries to convert obj to array if necessary
167
+ // raises error if obj not a kind of array and cannot be converted to one
168
+ // or if entry is not a number and cannot be converted to one.
156
169
 
157
170
 
158
171
  extern ID_PTR ID_Get(char *name);
data/split/Tioga/init.c CHANGED
@@ -54,9 +54,6 @@ static ID_PTR tex_fontfamily_ID;
54
54
  static ID_PTR tex_fontseries_ID;
55
55
  static ID_PTR tex_fontshape_ID;
56
56
  static ID_PTR line_type_ID;
57
- static ID_PTR title_ID;
58
- static ID_PTR xlabel_ID;
59
- static ID_PTR ylabel_ID;
60
57
  static ID_PTR xaxis_locations_for_major_ticks_ID;
61
58
  static ID_PTR xaxis_locations_for_minor_ticks_ID;
62
59
  static ID_PTR xaxis_tick_labels_ID;
@@ -313,8 +310,8 @@ static bool Get_quiet_mode(OBJ_PTR fmkr, int *ierr) {
313
310
 
314
311
  static void Make_Save_Fname(OBJ_PTR fmkr, char *full_name, char *f_name,
315
312
  bool with_save_dir, bool with_pdf_extension, int *ierr) {
316
- int i, j, k, len, mod_len, mod_num, did_mod_num = false;
317
- char c, *fmt, model[STRLEN], *save=NULL;
313
+ int i, j, len;
314
+ char c, *save=NULL;
318
315
  if (with_save_dir) { save = Get_save_dir(fmkr,ierr); if (*ierr != 0) return; }
319
316
  if (with_save_dir && save != NULL && strlen(save) > 0) {
320
317
  sprintf(full_name, "%s/", save); j = strlen(full_name); }
@@ -346,8 +343,7 @@ OBJ_PTR c_get_save_filename(OBJ_PTR fmkr, FM *p, OBJ_PTR name, int *ierr) {
346
343
 
347
344
 
348
345
  void c_private_make(OBJ_PTR fmkr, FM *p, OBJ_PTR name, OBJ_PTR cmd, int *ierr) {
349
- char full_name[STRLEN], mod_num_name[STRLEN];
350
- OBJ_PTR result;
346
+ char full_name[STRLEN];
351
347
  bool quiet = Get_quiet_mode(fmkr, ierr);
352
348
  if (*ierr != 0) return;
353
349
  if (!Get_initialized()) {
@@ -369,7 +365,6 @@ void c_private_make(OBJ_PTR fmkr, FM *p, OBJ_PTR name, OBJ_PTR cmd, int *ierr) {
369
365
  Call_Function(fmkr, make_page_ID, cmd, ierr);
370
366
  if (*ierr != 0) return;
371
367
  Write_grestore();
372
- if (result == OBJ_FALSE) quiet = true;
373
368
  Close_pdf(fmkr, p, quiet, ierr);
374
369
  if (*ierr != 0) return;
375
370
  Close_tex(fmkr, quiet, ierr);
@@ -578,10 +573,11 @@ void c_private_init_fm_data(OBJ_PTR fmkr, FM *p, int *ierr) {
578
573
  p->left_edge_visible = true;
579
574
  p->right_edge_type = EDGE_WITH_TICKS;
580
575
  p->right_edge_visible = true;
576
+
581
577
  /* Legend */
582
578
  p->legend_line_x0 = 0.5;
583
579
  p->legend_line_x1 = 2.0;
584
- p->legend_line_dy = 0.4;
580
+ p->legend_line_dy = 0.25;
585
581
  p->legend_text_width = -1;
586
582
  p->legend_text_xstart = 2.8;
587
583
  p->legend_text_ystart = 2.0;
@@ -90,16 +90,47 @@ Dictionary Entries
90
90
  end
91
91
 
92
92
  # Returns a vector of [ red, green, blue ] intensities corresponding to the
93
- # <i>hls_vec</i> color given as [ hue, lightness, saturation]. See also rgb_to_hls.
93
+ # <i>hls_vec</i> color given as [ hue, lightness, saturation ]. See also rgb_to_hls.
94
94
  def hls_to_rgb(hls_vec)
95
95
  end
96
96
 
97
97
  # Returns a vector of [ hue, lightness, saturation ] corresponding to the
98
- # <i>rgb_vec</i> color given as [ red, green, blue] intensities. See also hls_to_rgb.
98
+ # <i>rgb_vec</i> color given as [ red, green, blue ] intensities. See also hls_to_rgb.
99
99
  def rgb_to_hls(rgb_vec)
100
100
  end
101
101
 
102
102
 
103
+ # Returns a new string of [ red, green, blue ] byte triples corresponding to the
104
+ # colors given in <i>str</i> as triples of [ hue, lightness, saturation ].
105
+ # For representation as a byte, intensities in range 0.0 to 1.0 are multiplied by 255 and rounded;
106
+ # hue angles in the range 0.0 to 360.0 are divided by 360, multiplied by 255, and rounded.
107
+ # See also string_hls_to_rgb!.
108
+ def string_hls_to_rgb(str)
109
+ end
110
+
111
+ # Modifies in-place the string of [ red, green, blue ] byte triples to give the corresponding
112
+ # colors as triples of [ hue, lightness, saturation ].
113
+ # See also string_hls_to_rgb.
114
+ def string_hls_to_rgb!(str)
115
+ end
116
+
117
+ # Returns a new string of [ hue, lightness, saturation ] byte triples corresponding to the
118
+ # colors given in <i>str</i> as triples of [ red, green, blue ].
119
+ # For representation as a byte, intensities in range 0.0 to 1.0 are multiplied by 255 and rounded;
120
+ # hue angles in the range 0.0 to 360.0 are divided by 360, multiplied by 255, and rounded.
121
+ # See also string_rgb_to_hls!.
122
+ def string_rgb_to_hls(str)
123
+ end
124
+
125
+ # Modifies in-place the string of [ hue, lightness, saturation ] byte triples to give the corresponding
126
+ # colors as triples of [ red, green, blue ].
127
+ # See also string_rgb_to_hls.
128
+ def string_rgb_to_hls!(str)
129
+ end
130
+
131
+
132
+
133
+
103
134
 
104
135
  end # class
105
136
  end # module Tioga
@@ -77,6 +77,36 @@ class FigureMaker
77
77
  def FigureMaker.default=(fm)
78
78
  end
79
79
 
80
+ # :call-seq:
81
+ # FigureMaker.exec do |t| ... end
82
+ #
83
+ # Executes the block with FigureMaker.default as argument.
84
+ def FigureMaker.exec(&cmd)
85
+ end
86
+
87
+ # :call-seq:
88
+ # FigureMaker.make_pdf(name) do |t| ... end
89
+ #
90
+ # Executes the block to create a pdf with the given name.
91
+ # The argument for the block is FigureMaker.default.
92
+ def FigureMaker.make_pdf(name,&cmd)
93
+ end
94
+
95
+ # :call-seq:
96
+ # FigureMaker.def_enter_page_function do |t| ... end
97
+ #
98
+ # Defines the block to be the enter_page_function for FigureMaker.default.
99
+ def FigureMaker.def_enter_page_function(&cmd)
100
+ end
101
+
102
+ # :call-seq:
103
+ # FigureMaker.page_style do |t| ... end
104
+ #
105
+ # Alias for FigureMaker.def_enter_page_function.
106
+ # Defines the block to be the enter_page_function for FigureMaker.default.
107
+ def FigureMaker.page_style(&cmd)
108
+ end
109
+
80
110
  # :call-seq:
81
111
  # FigureMaker.version
82
112
  #
@@ -58,14 +58,16 @@ class Executive < Doc < FigureMaker
58
58
  end
59
59
 
60
60
  # :call-seq:
61
+ # make_pdf(name) do |t| ... end
61
62
  # make_pdf(name)
62
63
  # make_pdf(number)
63
64
  #
64
- # Executes the corresponding code that was previously saved by def_figure.
65
+ # First, if there is a command block given, def_figure is called to save it.
66
+ # Then make_pdf executes the command corresponding to the given name or number.
65
67
  # Output is written to the currently specified save_dir directory.
66
68
  # See also require_pdf.
67
69
  #
68
- def make_pdf(n)
70
+ def make_pdf(n,&cmd)
69
71
  end
70
72
 
71
73
  # :call-seq:
@@ -34,7 +34,7 @@ class FigureMaker
34
34
 
35
35
  # This URL will contain tioga-(...) when it is exported from the
36
36
  # SVN repository. This is where we'll look for version information.
37
- SVN_URL = '$HeadURL: svn+ssh://rubyforge.org/var/svn/tioga/tags/tioga/Tioga%201.8/split/Tioga/lib/FigMkr.rb $'
37
+ SVN_URL = '$HeadURL: svn+ssh://rubyforge.org/var/svn/tioga/trunk/tioga/split/Tioga/lib/FigMkr.rb $'
38
38
 
39
39
  TIOGA_VERSION = if SVN_URL =~ /tags\/tioga\/Tioga%20([^\/]+)/
40
40
  $1
@@ -66,14 +66,28 @@ class FigureMaker
66
66
  @@which_pdflatex = s
67
67
  end
68
68
 
69
-
70
69
  def FigureMaker.make_name_lookup_hash(ary)
71
70
  dict = Hash.new
72
71
  ary.each { |name| dict[name] = true }
73
72
  return dict
74
73
  end
75
-
76
-
74
+
75
+ def FigureMaker.make_pdf(name='immediate', &block)
76
+ self.default.make_pdf(name, &block)
77
+ end
78
+
79
+ def FigureMaker.def_enter_page_function(&cmd)
80
+ self.default.def_enter_page_function(&cmd)
81
+ end
82
+
83
+ def FigureMaker.page_style(&cmd)
84
+ FigureMaker.def_enter_page_function(&cmd)
85
+ end
86
+
87
+ def FigureMaker.exec(&cmd)
88
+ cmd.call(self.default)
89
+ end
90
+
77
91
 
78
92
  attr_accessor :title
79
93
  attr_accessor :xlabel
@@ -128,7 +142,7 @@ class FigureMaker
128
142
 
129
143
  attr_accessor :num_error_lines
130
144
 
131
- # Whether or not to create +save_dir+ if it doesn't exist
145
+ # Whether or not to create _save_dir_ if it doesn't exist
132
146
  attr_accessor :create_save_dir
133
147
 
134
148
  # Whether or not do do automatic cleanup of the files
@@ -140,6 +154,13 @@ class FigureMaker
140
154
  # An accessor for @measures_info:
141
155
  attr_accessor :measures_info
142
156
 
157
+
158
+
159
+ # If we want to use #legend_bounding_box. It is off by default
160
+ # as it causes a systematic second run of pdflatex.
161
+ attr_accessor :measure_legends
162
+
163
+
143
164
  # old preview attributes -- to be removed later
144
165
 
145
166
  attr_accessor :model_number
@@ -229,6 +250,7 @@ class FigureMaker
229
250
  'plot_left_margin' => 0.0,
230
251
  'plot_right_margin' => 0.18,
231
252
  'plot_scale' => 1,
253
+ 'legend_background_function' => false,
232
254
  'legend_scale' => 1 }
233
255
 
234
256
  @marker_defaults = {
@@ -279,6 +301,12 @@ class FigureMaker
279
301
 
280
302
  # We *must* initialize the measures_info hash.
281
303
  @measures_info = {}
304
+
305
+ # We don't measure legends by default.
306
+ @measure_legends = false
307
+
308
+ # By default, we use Bill's algorithm for major ticks positions
309
+ self.vincent_or_bill = false
282
310
  end
283
311
 
284
312
 
@@ -611,6 +639,7 @@ class FigureMaker
611
639
  'marker_scale' => nil,
612
640
  }
613
641
 
642
+
614
643
  def save_legend_info(arg)
615
644
  if arg.kind_of?String
616
645
  dict = { 'text' => arg }
@@ -625,8 +654,9 @@ class FigureMaker
625
654
  end
626
655
  @legend_info << dict
627
656
  end
657
+
628
658
 
629
- def show_legend
659
+ def show_legend(legend_background_function=nil)
630
660
  char_dx = self.default_text_height_dx
631
661
  char_dy = self.default_text_height_dy
632
662
  line_ht_x = char_dx * self.legend_scale
@@ -641,20 +671,48 @@ class FigureMaker
641
671
  end
642
672
  end
643
673
  xright = x + ltw*line_ht_x
674
+
644
675
  y = 1.0 - self.legend_text_ystart*line_ht_y
645
676
  update_bbox(xright, y)
646
- dy = -self.legend_text_dy*line_ht_y
647
677
  line_x0 = self.legend_line_x0*line_ht_x
648
678
  line_x1 = self.legend_line_x1*line_ht_x
649
679
  line_dy = self.legend_line_dy*line_ht_y
680
+
681
+ # If we are measuring legends, we come up with a more
682
+ # accurate version of xright:
683
+ if @measure_legends
684
+ xright = x + convert_output_to_figure_dx(legend_text_width)
685
+ xright += line_x0 # To leave a symetric space around
686
+ # the legend !
687
+ end
688
+
650
689
  self.label_left_margin = self.label_right_margin = self.label_top_margin = self.label_bottom_margin = -1e99
690
+ unless legend_background_function == nil || legend_background_function == false
691
+ ybot = y
692
+ # we need to remove the first element ;-)...
693
+ @legend_info[1..-1].each do |dict|
694
+ dy = dict['dy']; dy = 1 if dy == nil
695
+ ybot -= line_ht_y * dy
696
+ end
697
+ # We add half a line below to look good
698
+ ybot -= line_ht_y * 0.5
699
+ ytop = y + @legend_info.first['dy'] * line_ht_y * 0.5
700
+ legend_background_function.call([ 0, xright, ytop, ybot ])
701
+ end
702
+ legend_index = 0
651
703
  @legend_info.each do |dict|
652
704
  text = dict['text']
653
705
  if text != nil
654
- show_text('text' => text,
655
- 'x' => x, 'y' => y, 'scale' => self.legend_scale,
656
- 'justification' => self.legend_justification,
657
- 'alignment' => self.legend_alignment)
706
+ # We prepare a dictionnary:
707
+ dct = { 'text' => text,
708
+ 'x' => x, 'y' => y, 'scale' => self.legend_scale,
709
+ 'justification' => self.legend_justification,
710
+ 'alignment' => self.legend_alignment }
711
+ if @measure_legends
712
+ dct['measure'] = "legend-#{legend_index}"
713
+ legend_index += 1
714
+ end
715
+ show_text(dct)
658
716
  end
659
717
  line_width = dict['line_width']
660
718
  line_type = dict['line_type']
@@ -683,6 +741,20 @@ class FigureMaker
683
741
  end
684
742
  end
685
743
 
744
+ # Returns the exact length of the text width in output
745
+ # coordinates
746
+ def legend_text_width
747
+ index = 0
748
+ width = 0.0
749
+ while h = get_text_size("legend-#{index}") and h.key?('width')
750
+ if width < h['width']
751
+ width = h['width']
752
+ end
753
+ index += 1
754
+ end
755
+ return 10 * width
756
+ end
757
+
686
758
  def legend_height
687
759
  height = 0.0
688
760
  @legend_info.each { |dict| height += dict['dy'] }
@@ -808,17 +880,17 @@ class FigureMaker
808
880
 
809
881
  unless entry_function == nil
810
882
  begin
811
- entry_function.call
883
+ entry_function.call(self)
812
884
  rescue Exception => er
813
885
  report_error(er, nil)
814
886
  end
815
887
  end
816
888
 
817
- result = cmd.call
889
+ result = cmd.call(self)
818
890
 
819
891
  unless exit_function == nil
820
892
  begin
821
- exit_function.call
893
+ exit_function.call(self)
822
894
  rescue Exception => er
823
895
  report_error(er, nil)
824
896
  end
@@ -839,7 +911,7 @@ class FigureMaker
839
911
  end
840
912
  end
841
913
 
842
- result = cmd.call
914
+ result = cmd.call(self)
843
915
 
844
916
  unless exit_function == nil
845
917
  begin
@@ -857,14 +929,24 @@ class FigureMaker
857
929
  def show_plot(bounds=nil,&cmd)
858
930
  trace_cmd_one_arg(@enter_show_plot_function, @exit_show_plot_function, bounds) {
859
931
  set_bounds(bounds)
860
- context { clip_to_frame; cmd.call }
932
+ context { clip_to_frame; cmd.call(self) }
861
933
  show_plot_box
862
934
  }
863
935
  end
864
936
 
937
+
938
+ def show_plot_without_clipping(bounds=nil,&cmd)
939
+ trace_cmd_one_arg(@enter_show_plot_function, @exit_show_plot_function, bounds) {
940
+ set_bounds(bounds)
941
+ context { cmd.call(self) }
942
+ show_plot_box
943
+ }
944
+ end
945
+
946
+
865
947
  def subfigure(margins=nil,&cmd)
866
948
  trace_cmd_one_arg(@enter_subfigure_function, @exit_subfigure_function, margins) {
867
- context { doing_subfigure; set_subframe(margins); cmd.call }
949
+ context { doing_subfigure; set_subframe(margins); cmd.call(self) }
868
950
  }
869
951
  end
870
952
 
@@ -879,7 +961,7 @@ class FigureMaker
879
961
  def subplot(margins=nil,&cmd)
880
962
  trace_cmd_one_arg(@enter_subplot_function, @exit_subplot_function, margins) {
881
963
  reset_legend_info
882
- context { doing_subplot; set_subframe(margins); cmd.call }
964
+ context { doing_subplot; set_subframe(margins); cmd.call(self) }
883
965
  }
884
966
  end
885
967
 
@@ -957,7 +1039,7 @@ class FigureMaker
957
1039
  save_fm_data = Dvector.new(@@fm_data_size).replace(@fm_data)
958
1040
  pdf_gsave
959
1041
  begin
960
- cmd.call
1042
+ cmd.call(self)
961
1043
  ensure
962
1044
  pdf_grestore
963
1045
  self.title = save_title
@@ -1066,10 +1148,92 @@ class FigureMaker
1066
1148
  end
1067
1149
  end
1068
1150
 
1151
+ @@keys_for_show_grid = %w[
1152
+ stroke_color line_type rescale_lines line_width stroke_opacity stroke_transparency
1153
+ ]
1154
+
1155
+ # Draws the gridlines associated with the X and Y axis.
1156
+ #
1157
+ # The following list shows the keys that cen be used in +dict+. In the
1158
+ # list, 'A' stands for either 'x' or 'y', and 'M' stands for 'major' or
1159
+ # 'minor'. Keys can also be specified without the "A_M_" prefix to specify
1160
+ # "grid-global" defaults. The +grid+ key, if true, enables both major and
1161
+ # minor gridlines for both x and y axes.
1162
+ #
1163
+ # * A_M_grid
1164
+ # * A_M_line_type
1165
+ # * A_M_line_width
1166
+ # * A_M_stroke_opacity
1167
+ # * A_M_stroke_transparency
1168
+ # * A_M_stroke_color
1169
+ def show_grid(dict={})
1170
+ dict = {
1171
+ 'line_type' => Line_Type_Dot,
1172
+ 'rescale_lines' => 0.25,
1173
+ 'stroke_color' => Gray,
1174
+ 'major_grid' => true,
1175
+ 'minor_grid' => false,
1176
+ 'x_minor_rescale_lines' => 0.5,
1177
+ 'y_minor_rescale_lines' => 0.5,
1178
+ }.merge(dict)
1179
+
1180
+ # "grid-global" context
1181
+ context do
1182
+ @@keys_for_show_grid.each do |k|
1183
+ next unless val = dict[k]
1184
+ k += '=' if respond_to? "#{k}="
1185
+ next unless respond_to? k
1186
+ send(k, val)
1187
+ end
1188
+
1189
+ if dict['x_major_grid'] || dict['x_minor_grid'] ||
1190
+ dict[ 'major_grid'] || dict[ 'minor_grid'] || dict['grid']
1191
+ top = axis_information(TOP)
1192
+ bottom = axis_information(BOTTOM)
1193
+ y0 = bottom['y0']
1194
+ y1 = top['y1']
1195
+ # Do minor and major grid lines in same context so minor lines will
1196
+ # inherit properties from major lines.
1197
+ context do
1198
+ %w[ major minor ].each do |m|
1199
+ next unless dict["x_#{m}_grid"] || dict["#{m}_grid"] || dict["grid"]
1200
+ @@keys_for_show_grid.each do |k|
1201
+ next unless val = dict["x_#{m}_#{k}"]
1202
+ k += '=' if respond_to? "#{k}="
1203
+ send(k, val)
1204
+ end
1205
+ bottom[m].each {|x| stroke_line(x, y0, x, y1)}
1206
+ end
1207
+ end
1208
+ end
1209
+
1210
+ if dict['y_major_grid'] || dict['y_minor_grid'] ||
1211
+ dict[ 'major_grid'] || dict[ 'minor_grid'] || dict['grid']
1212
+ left = axis_information(LEFT)
1213
+ right = axis_information(RIGHT)
1214
+ x0 = left['x0']
1215
+ x1 = right['x1']
1216
+ # Do minor and major grid lines in same context so minor lines will
1217
+ # inherit properties from major lines.
1218
+ context do
1219
+ %w[ major minor ].each do |m|
1220
+ next unless dict["y_#{m}_grid"] || dict["#{m}_grid"] || dict["grid"]
1221
+ @@keys_for_show_grid.each do |k|
1222
+ next unless val = dict["y_#{m}_#{k}"]
1223
+ k += '=' if respond_to? "#{k}="
1224
+ send(k, val)
1225
+ end
1226
+ left[m].each {|y| stroke_line(x0, y, x1, y)}
1227
+ end
1228
+ end
1229
+ end
1230
+ end
1231
+ end
1232
+
1069
1233
  @@keys_for_show_plot_with_legend = FigureMaker.make_name_lookup_hash([
1070
1234
  'legend_top_margin', 'legend_bottom_margin', 'legend_left_margin', 'legend_right_margin',
1071
1235
  'plot_top_margin', 'plot_bottom_margin', 'plot_left_margin', 'plot_right_margin',
1072
- 'plot_scale', 'legend_scale' ])
1236
+ 'plot_scale', 'legend_scale', 'legend_background_function' ])
1073
1237
  def show_plot_with_legend(dict=nil, &cmd)
1074
1238
  check_dict(dict, @@keys_for_show_plot_with_legend, 'show_plot_with_legend') if dict != nil
1075
1239
  legend_top_margin = get_if_given_else_use_default_dict(dict, 'legend_top_margin', @legend_defaults)
@@ -1082,13 +1246,18 @@ class FigureMaker
1082
1246
  plot_left_margin = get_if_given_else_use_default_dict(dict, 'plot_left_margin', @legend_defaults)
1083
1247
  plot_right_margin = get_if_given_else_use_default_dict(dict, 'plot_right_margin', @legend_defaults)
1084
1248
  plot_scale = get_if_given_else_use_default_dict(dict, 'plot_scale', @legend_defaults)
1249
+ legend_background_function = get_if_given_else_default(dict, 'legend_background_function', nil)
1250
+ @legend_subframe = [legend_left_margin, legend_right_margin,
1251
+ legend_top_margin, legend_bottom_margin]
1085
1252
  reset_legend_info
1086
1253
  rescale(plot_scale)
1087
- subplot([plot_left_margin, plot_right_margin, plot_top_margin, plot_bottom_margin]) { cmd.call }
1088
- set_subframe([legend_left_margin, legend_right_margin, legend_top_margin, legend_bottom_margin])
1254
+ subplot([plot_left_margin, plot_right_margin, plot_top_margin, plot_bottom_margin]) { cmd.call(self) }
1255
+ # We temporary store the legend information in @legend_subframes
1256
+ set_subframe(@legend_subframe)
1089
1257
  rescale(legend_scale) # note that legend_scale is an addition to the plot_scale, not a replacement
1090
1258
  @pr_margin = plot_right_margin
1091
- show_legend
1259
+ show_legend(legend_background_function)
1260
+ @legend_subframe = nil
1092
1261
  end
1093
1262
 
1094
1263
  def append_points_with_gaps_to_path(xs, ys, gaps, close_subpaths = false)
@@ -1439,6 +1608,17 @@ class FigureMaker
1439
1608
  extend_start, extend_end)
1440
1609
  end
1441
1610
 
1611
+
1612
+ def string_hls_to_rgb(str)
1613
+ string_hls_to_rgb!(String.new(str))
1614
+ end
1615
+
1616
+
1617
+ def string_rgb_to_hls(str)
1618
+ string_rgb_to_hls!(String.new(str))
1619
+ end
1620
+
1621
+
1442
1622
  @@keys_for_show_image = FigureMaker.make_name_lookup_hash([
1443
1623
  'll', 'lr', 'ul', 'w', 'width', 'height', 'h',
1444
1624
  'opacity_mask', 'stencil_mask',
@@ -1624,27 +1804,7 @@ class FigureMaker
1624
1804
  if (marker != nil && string != nil)
1625
1805
  raise "Sorry: Must give either 'marker' or 'string' for show_marker, but not both"
1626
1806
  end
1627
- if (marker == nil)
1628
- glyph = stroke_width = nil
1629
- else
1630
- if !(marker.kind_of?Array) && marker.size >= 2 && marker.size <= 3
1631
- raise "Sorry: 'marker' for show_marker must be array of [font_number, char_code] or [font_number, char_code, rendering_mode]"
1632
- end
1633
- font = marker[0]
1634
- glyph = marker[1]
1635
- if marker.size == 3
1636
- mode = STROKE if mode == nil
1637
- stroke_width = marker[2]
1638
- else
1639
- mode = FILL if mode == nil
1640
- stroke_width = nil
1641
- end
1642
- end
1643
- mode = FILL if mode == nil
1644
- font = Times_Roman if (font == nil && string != nil)
1645
- if (font != nil && !(font.kind_of? Integer))
1646
- raise "Sorry: 'font' for show_marker must be an integer font number (see FigureConstants list)"
1647
- end
1807
+
1648
1808
  stroke_width = get_if_given_else_default(dict, 'stroke_width', stroke_width)
1649
1809
  angle = get_if_given_else_use_default_dict(dict, 'angle', @marker_defaults)
1650
1810
  scale = get_if_given_else_use_default_dict(dict, 'scale', @marker_defaults)
@@ -1655,10 +1815,11 @@ class FigureMaker
1655
1815
  it_angle = get_if_given_else_use_default_dict(dict, 'italic_angle', @marker_defaults)
1656
1816
  ascent_angle = get_if_given_else_use_default_dict(dict, 'ascent_angle', @marker_defaults)
1657
1817
  glyph = 0 if glyph == nil
1658
- int_args = glyph*100000 + font*1000 + mode*100 + align*10 + (just+1) # min value for just is -1
1659
- # Ruby limits us to 15 args, so pack some small integers together
1660
- private_show_marker(int_args, stroke_width, string, x, y, xs, ys,
1661
- h_scale, v_scale, scale, it_angle, ascent_angle, angle, fill_color, stroke_color)
1818
+
1819
+ args = [marker, font, mode, align, just, stroke_width, string, x, y, xs, ys,
1820
+ h_scale, v_scale, scale, it_angle, ascent_angle, angle, fill_color, stroke_color]
1821
+ private_show_marker(args)
1822
+
1662
1823
  legend_arg = dict['legend']
1663
1824
  if legend_arg != nil
1664
1825
  if legend_arg.kind_of?Hash
@@ -1784,7 +1945,6 @@ class FigureMaker
1784
1945
  end
1785
1946
 
1786
1947
 
1787
-
1788
1948
  def def_enter_page_function(&cmd)
1789
1949
  if cmd == nil
1790
1950
  raise "Sorry: must provide a command block for def_enter_page_function"
@@ -1950,7 +2110,8 @@ class FigureMaker
1950
2110
 
1951
2111
  # We wrap the call so that if the keys of @measures
1952
2112
  # did change during the call, we call it again.
1953
- def make_pdf(num) # returns pdf name if successful, false if failed.
2113
+ def make_pdf(num,&cmd) # returns pdf name if successful, false if failed.
2114
+ def_figure(num,&cmd) if Kernel.block_given?
1954
2115
  old_measure_keys = @measures.keys
1955
2116
  num = get_num_for_pdf(num)
1956
2117
  result = start_making_pdf(num)
@@ -1963,6 +2124,7 @@ class FigureMaker
1963
2124
  end
1964
2125
 
1965
2126
  if @measures.keys != old_measure_keys
2127
+ # we dont need to pass &cmd since it has now been defined
1966
2128
  make_pdf(num)
1967
2129
  end
1968
2130
  return @figure_pdfs[num]
@@ -2259,6 +2421,10 @@ class FigureMaker
2259
2421
  private_show_rgb_image(ll[0], ll[1], lr[0], lr[1], ul[0], ul[1], interpolate, w, h, data, mask_xo_num)
2260
2422
  return self
2261
2423
  end
2424
+ if color_space == 'HLS' || color_space == 'hls'
2425
+ private_show_hls_image(ll[0], ll[1], lr[0], lr[1], ul[0], ul[1], interpolate, w, h, data, mask_xo_num)
2426
+ return self
2427
+ end
2262
2428
  if color_space == 'CMYK' || color_space == 'cmyk'
2263
2429
  private_show_cmyk_image(ll[0], ll[1], lr[0], lr[1], ul[0], ul[1], interpolate, w, h, data, mask_xo_num)
2264
2430
  return self
@@ -2310,7 +2476,7 @@ class FigureMaker
2310
2476
  exit_function = @exit_page_function
2311
2477
  unless entry_function == nil
2312
2478
  begin
2313
- entry_result = entry_function.call
2479
+ entry_result = entry_function.call(self)
2314
2480
  rescue Exception => er
2315
2481
  report_error(er, nil)
2316
2482
  end
@@ -2318,7 +2484,7 @@ class FigureMaker
2318
2484
  result = do_cmd(cmd)
2319
2485
  unless result == false or exit_function == nil
2320
2486
  begin
2321
- exit_result = exit_function.call
2487
+ exit_result = exit_function.call(self)
2322
2488
  rescue Exception => er
2323
2489
  report_error(er, nil)
2324
2490
  end
@@ -2329,7 +2495,7 @@ class FigureMaker
2329
2495
 
2330
2496
  def do_cmd(cmd) # the C implementation uses this to call Ruby commands
2331
2497
  begin
2332
- cmd.call
2498
+ cmd.call(self)
2333
2499
  return true
2334
2500
  rescue Exception => er
2335
2501
  report_error(er, nil)