tioga 1.8 → 1.9

Sign up to get free protection for your applications and to get access to all the features.
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)