tioga 1.6 → 1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Tioga_README +35 -10
- data/split/Dvector/dvector.c +264 -22
- data/split/Dvector/lib/Dvector_extras.rb +30 -2
- data/split/Flate/extconf.rb +1 -1
- data/split/Function/function.c +112 -2
- data/split/Tioga/figures.c +76 -77
- data/split/Tioga/figures.h +375 -490
- data/split/Tioga/generic.c +254 -0
- data/split/Tioga/generic.h +236 -0
- data/split/Tioga/init.c +434 -320
- data/split/Tioga/lib/Creating_Paths.rb +11 -1
- data/split/Tioga/lib/FigMkr.rb +263 -65
- data/split/Tioga/lib/Legends.rb +4 -2
- data/split/Tioga/lib/Markers.rb +3 -2
- data/split/Tioga/lib/Special_Paths.rb +22 -23
- data/split/Tioga/lib/TeX_Text.rb +79 -1
- data/split/Tioga/lib/TexPreamble.rb +14 -0
- data/split/Tioga/lib/Utils.rb +5 -1
- data/split/Tioga/pdfs.h +7 -45
- data/split/Tioga/{axes.c → shared/axes.c} +210 -197
- data/split/Tioga/{makers.c → shared/makers.c} +442 -211
- data/split/Tioga/{pdf_font_dicts.c → shared/pdf_font_dicts.c} +0 -0
- data/split/Tioga/shared/pdfcolor.c +628 -0
- data/split/Tioga/shared/pdfcoords.c +443 -0
- data/split/Tioga/{pdffile.c → shared/pdffile.c} +56 -52
- data/split/Tioga/{pdfimage.c → shared/pdfimage.c} +103 -211
- data/split/Tioga/shared/pdfpath.c +766 -0
- data/split/Tioga/{pdftext.c → shared/pdftext.c} +121 -99
- data/split/Tioga/shared/texout.c +524 -0
- data/split/Tioga/wrappers.c +489 -0
- data/split/Tioga/wrappers.h +259 -0
- data/split/extconf.rb +4 -0
- data/split/mkmf2.rb +12 -1
- data/tests/benchmark_dvector_reads.rb +112 -0
- data/tests/tc_Dvector.rb +35 -3
- data/tests/tc_Function.rb +32 -0
- metadata +65 -52
- data/split/Tioga/pdfcolor.c +0 -486
- data/split/Tioga/pdfcoords.c +0 -523
- data/split/Tioga/pdfpath.c +0 -913
- data/split/Tioga/texout.c +0 -380
data/split/Tioga/lib/Legends.rb
CHANGED
@@ -44,7 +44,7 @@ Dictionary Entries
|
|
44
44
|
'line_color' => a_color # defaults to self.line_color
|
45
45
|
'line_width' => a_float # defaults to self.line_width
|
46
46
|
'line_cap' => a_line_cap # defaults to self.line_cap
|
47
|
-
'line_type' => a_line_type # defaults to self.line_type
|
47
|
+
'line_type' => a_line_type or 'None' # defaults to self.line_type
|
48
48
|
'dy' => a_float # defaults to self.legend_text_dy
|
49
49
|
'marker' => a_marker # defaults to nil
|
50
50
|
'marker_color' => a_color # defaults to self.line_color
|
@@ -55,7 +55,9 @@ The dictionary holding the information is appended to the legend_info array. If
|
|
55
55
|
then the marker with the given 'marker_color' and 'marker_scale' will be shown in the middle of the
|
56
56
|
legend line. If the 'marker_dict' entry is present, it will have the values for 'x' and 'y' set to the location
|
57
57
|
of the middle of the legend line and then it will be passed to the show_marker method. This gives you the option of using
|
58
|
-
the full range of marker functionality in legends -- perhaps you'd like to use a line marker that is rotated,
|
58
|
+
the full range of marker functionality in legends -- perhaps you'd like to use a line marker that is rotated,
|
59
|
+
stretched, filled in one color, and stroked in another! Sometimes you just want to have a marker in
|
60
|
+
the legend without a line; do this by setting line_type to 'None'.
|
59
61
|
|
60
62
|
=end
|
61
63
|
def save_legend_info(arg)
|
data/split/Tioga/lib/Markers.rb
CHANGED
@@ -28,7 +28,7 @@ Computer Modern fonts which are likely to be around since they come with TeX. T
|
|
28
28
|
in the FigureConstants module. Any character (or string of characters) from any of these fonts can be used as a marker.
|
29
29
|
|
30
30
|
Because markers are sent to PDF rather than TeX, they are limited typographically but powerful graphically.
|
31
|
-
In addition to specifying color, scale, and
|
31
|
+
In addition to specifying color, scale, and rotation, as you can for TeX text, you can also stretch
|
32
32
|
the characters either along the baseline ('horizontal_scale') or perpendicular to it ('vertical_scale').
|
33
33
|
You can slant the individual characters ('italic_angle') or shift the baseline along the text ('ascent_angle').
|
34
34
|
Finally, you can specify the 'rendering_mode' for the marker to be any combination of #fill, #stroke, and #clip.
|
@@ -64,6 +64,7 @@ Dictionary Entries
|
|
64
64
|
'rendering_mode' => a_rendering_mode # see below
|
65
65
|
'stroke_width' => a_float # to be used for stroked markers
|
66
66
|
'mode' # alias for 'rendering_mode'
|
67
|
+
'legend' => a_dict or a_string # for adding marker to legend
|
67
68
|
|
68
69
|
|
69
70
|
Examples
|
@@ -109,7 +110,7 @@ link:images/Marker_Shadow_Effect.png
|
|
109
110
|
def show_marker(dict)
|
110
111
|
end
|
111
112
|
|
112
|
-
# Returns an array with [_width_, <i>dx_left</i>, <i>
|
113
|
+
# Returns an array with [_width_, <i>dx_left</i>, <i>dy_down</i>, <i>dx_right</i>, <i>dy_up</i>] given in
|
113
114
|
# figure coordinates. The first is the width in figure x coordinates, the remainder is the bounding box
|
114
115
|
# relative to the reference point for showing the string.
|
115
116
|
def marker_string_info(font_number, string, scale)
|
@@ -11,7 +11,8 @@ Creates a path following a contour in a two dimensional table of data using an a
|
|
11
11
|
Gri[http://gri.sourceforge.net/] done by Dan Kelley.
|
12
12
|
(There is also an option to use the
|
13
13
|
CONREC[http://local.wasp.uwa.edu.au/~pbourke/papers/conrec/] algorithm of Paul D. Bourke.)
|
14
|
-
|
14
|
+
The results are returned in 2-element array with first element a vector of the x values for
|
15
|
+
the contour and second element a vector of the y values. See show_contour.
|
15
16
|
|
16
17
|
Dictionary Entries
|
17
18
|
'zs' => a_dtable # The data table
|
@@ -19,8 +20,8 @@ Dictionary Entries
|
|
19
20
|
'xs' => a_dvector # The x figure coordinates for the columns of data
|
20
21
|
'ys' => a_dvector # The y figure coordinates for the rows of data
|
21
22
|
'legit' => a_dtable # Optional table, same size as zs, non-zero means corresponding data is okay.
|
22
|
-
'dest_xs' => a_dvector # The contour x values will be placed in this
|
23
|
-
'dest_ys' => a_dvector # The contour y values will be placed in this
|
23
|
+
'dest_xs' => a_dvector # The contour x values will be placed in this vector (optional).
|
24
|
+
'dest_ys' => a_dvector # The contour y values will be placed in this vector (optional).
|
24
25
|
'gaps' => an_array # Indices for gaps will be placed in this Array.
|
25
26
|
'z_level' => a_float # The contour level
|
26
27
|
'z' # Alias for 'z_level'
|
@@ -34,14 +35,11 @@ Example
|
|
34
35
|
clip_press_image
|
35
36
|
t.stroke_color = SlateGray
|
36
37
|
t.line_width = 1
|
37
|
-
|
38
|
-
dict = { 'dest_xs' => dest_xs, 'dest_ys' => dest_ys, 'gaps' => gaps,
|
39
|
-
'xs' => @eos_logRHOs, 'ys' => @eos_logTs,
|
40
|
-
'data' => @pres_data }
|
38
|
+
dict = { 'gaps' => gaps, 'xs' => @eos_logRHOs, 'ys' => @eos_logTs, 'data' => @pres_data }
|
41
39
|
levels.each do |level|
|
42
40
|
dict['level'] = level
|
43
|
-
t.make_contour(dict)
|
44
|
-
t.append_points_with_gaps_to_path(
|
41
|
+
pts_array = t.make_contour(dict)
|
42
|
+
t.append_points_with_gaps_to_path(pts_array[0], pts_array[1], gaps, true)
|
45
43
|
t.stroke
|
46
44
|
end
|
47
45
|
end
|
@@ -53,7 +51,9 @@ link:images/Contours.png
|
|
53
51
|
end
|
54
52
|
|
55
53
|
=begin rdoc
|
56
|
-
Creates a 'staircase' path with steps matching the given data points
|
54
|
+
Creates a 'staircase' path with steps matching the given data points;
|
55
|
+
returns 2-element array with first element a vector of the x values for
|
56
|
+
the steps and second element a vector of the y values.
|
57
57
|
|
58
58
|
Dictionary Entries
|
59
59
|
'xfirst' => a_float # x location for the start of the steps
|
@@ -66,12 +66,13 @@ Dictionary Entries
|
|
66
66
|
'y_last' # Alias for 'ylast'
|
67
67
|
'xs' => a_dvector # The data x in figure coordinates
|
68
68
|
'ys' => a_dvector # The data y in figure coordinates
|
69
|
-
'dest_xs' => a_dvector # The x values for the steps will go here.
|
70
|
-
'dest_ys' => a_dvector # The y values for the steps will go here.
|
69
|
+
'dest_xs' => a_dvector # The x values for the steps will go here (optional).
|
70
|
+
'dest_ys' => a_dvector # The y values for the steps will go here (optional).
|
71
71
|
|
72
72
|
The widths of steps are determined by 'xfirst', 'xs', and 'xlast'; the heights of steps are
|
73
73
|
determined by 'yfirst', 'ys', and 'ylast'. The steps up and down occur at the midpoints between
|
74
|
-
the given x locations.
|
74
|
+
the given x locations. If 'dest_xs' are given in the dictionary, that vector will be set to
|
75
|
+
the x values for the steps. Similarly for 'dest_ys'.
|
75
76
|
|
76
77
|
Example
|
77
78
|
|
@@ -83,16 +84,15 @@ Example
|
|
83
84
|
x_first = 0.0; x_last = 18.0; y_first = y_last = 2.5
|
84
85
|
x_results = Dvector[]
|
85
86
|
y_results = Dvector[]
|
86
|
-
t.make_steps(
|
87
|
+
stps = t.make_steps(
|
87
88
|
'xs' => xs, 'ys' => ys,
|
88
|
-
'dest_xs' => x_results, 'dest_ys' => y_results,
|
89
89
|
'x_first' => x_first, 'y_first' => y_first,
|
90
90
|
'x_last' => x_last, 'y_last' => y_last)
|
91
91
|
t.show_plot('boundaries' => [-1, 19, 8, 2]) do
|
92
92
|
t.fill_color = FloralWhite
|
93
93
|
t.fill_frame
|
94
94
|
t.stroke_color = Blue
|
95
|
-
t.append_points_to_path(
|
95
|
+
t.append_points_to_path(stps[0], stps[1])
|
96
96
|
t.stroke
|
97
97
|
t.show_marker('Xs' => xs, 'Ys' => ys, 'marker' => Bullet,
|
98
98
|
'scale' => 0.6, 'color' => Red);
|
@@ -108,6 +108,7 @@ link:images/Steps.png
|
|
108
108
|
Creates an interpolated series of points smoothly connecting the given data points.
|
109
109
|
See also append_interpolant_to_path for creating smooth paths based on
|
110
110
|
Bezier curves rather than on sampled points joined by straight line segments.
|
111
|
+
Returns a vector of the y values corresponding to the requested 'sample_ys'.
|
111
112
|
|
112
113
|
Dictionary Entries
|
113
114
|
'start_slope' => a_float # optional
|
@@ -115,12 +116,12 @@ Dictionary Entries
|
|
115
116
|
'xs' => a_dvector # The data x in figure coordinates
|
116
117
|
'ys' => a_dvector # The data y in figure coordinates
|
117
118
|
'sample_xs' => a_dvector # The x values where will interpolate
|
118
|
-
'result_ys' => a_dvector # The y values will be placed here.
|
119
|
+
'result_ys' => a_dvector # The y values will be placed here (optional).
|
119
120
|
|
120
121
|
A cubic spline interpolant is created (see make_interpolant) using 'start_slope', 'end_slope', 'xs', and
|
121
122
|
'ys'. At each x location in 'sample_xs', the interpolant is used to find the corresponding y location
|
122
|
-
which is then placed in the 'result_ys' vector.
|
123
|
-
append_points_to_path or show_polyline.
|
123
|
+
which is then returned as the value (and optionally also placed in the 'result_ys' vector).
|
124
|
+
The results can passed to routines such as append_points_to_path or show_polyline.
|
124
125
|
|
125
126
|
Example
|
126
127
|
|
@@ -143,10 +144,8 @@ Example
|
|
143
144
|
smooth_pts = 4*(data_pts-1) + 1
|
144
145
|
dx = (xs[data_pts-1] - xs[0])/(smooth_pts-1)
|
145
146
|
sample_xs = Dvector.new(smooth_pts) { |i| i*dx + xs[0] }
|
146
|
-
result_ys =
|
147
|
-
|
148
|
-
'sample_xs' => sample_xs, 'result_ys' => result_ys,
|
149
|
-
'xs' => xs, 'ys' => ys,
|
147
|
+
result_ys = t.make_spline_interpolated_points(
|
148
|
+
'sample_xs' => sample_xs, 'xs' => xs, 'ys' => ys,
|
150
149
|
'start_slope' => 2.5*(ys[1]-ys[0])/(xs[1]-xs[0]))
|
151
150
|
t.stroke_color = Blue
|
152
151
|
t.append_points_to_path(sample_xs, result_ys)
|
data/split/Tioga/lib/TeX_Text.rb
CHANGED
@@ -61,6 +61,10 @@ With double quotes, Ruby uses backslash for a variety of escape characters such
|
|
61
61
|
so the backslashes for TeX need to be entered as \\ pairs to be safe.
|
62
62
|
Compare '$\nu\sim\tau$' to the equivalent form "$\\\\nu\\\\sim\\\\tau$" and the incorrect form "$\nu\sim\tau$".
|
63
63
|
|
64
|
+
Starting from Tioga 1.7, Tioga can measure the TeX text it typesets. For
|
65
|
+
that purpose, provide #show_text with a 'measure' dictionnary entry that
|
66
|
+
serves as a key to retrieve the information using #get_text_size.
|
67
|
+
|
64
68
|
Dictionary Entries
|
65
69
|
'text' => a_string # to be processed by TeX
|
66
70
|
'side' => a_side # TOP, BOTTOM, LEFT, or RIGHT
|
@@ -77,7 +81,8 @@ Dictionary Entries
|
|
77
81
|
'angle' => a_float # degrees to rotate. default 0
|
78
82
|
'alignment' => an_alignment # see discussion of alignment
|
79
83
|
'justification' => a_justification # see discussion of justification
|
80
|
-
|
84
|
+
'measure' => a_string # the name of the measure
|
85
|
+
|
81
86
|
Examples
|
82
87
|
|
83
88
|
def math_typesetting
|
@@ -204,6 +209,79 @@ link:images/Framebox.png
|
|
204
209
|
def show_text(dict)
|
205
210
|
end
|
206
211
|
|
212
|
+
=begin rdoc
|
213
|
+
Returns information about the text measure named _name_. It returns a hash
|
214
|
+
with the following information:
|
215
|
+
|
216
|
+
* _[xy][tb][lr]_ the X/Y coordinates of the Top/Bottom Left/Right point of the
|
217
|
+
box around the text (top, left, right and bottom are relative to the text
|
218
|
+
natural orientation)
|
219
|
+
* _just_ the text justification
|
220
|
+
* _angle_ the text's angle, in degrees
|
221
|
+
* _tex_measured_depth_, _tex_measured_height_, tex_measured_width_, the
|
222
|
+
text's depth, width and height as measured by TeX,
|
223
|
+
(does not take scaling into accound)
|
224
|
+
* _xanchor_, _yanchor_: the page coordinates of the position of the text
|
225
|
+
(the ones that were given to #show_text)
|
226
|
+
* _points_ an array of (x,y) coordinates of the points that make the box,
|
227
|
+
in the order bottom left, bottom right, top right, top left.
|
228
|
+
* _depth_, _width_, _height_ : the size of the text.
|
229
|
+
* _align_ the alignment of the text
|
230
|
+
|
231
|
+
All the measures are given in postscript points, which means you need
|
232
|
+
to multiply by 10 before using the with
|
233
|
+
Page_Frame_Bounds#convert_output_to_figure_x
|
234
|
+
Page_Frame_Bounds#convert_output_to_figure_y. See the example
|
235
|
+
|
236
|
+
Please make sure you test the presence of one key before using it, as
|
237
|
+
any code using measures has to run *twice*: one first time to typeset the
|
238
|
+
text and ask LaTeX for information about its size, and the second time to
|
239
|
+
actually use the information. You don't need to call the code twice as it
|
240
|
+
is done automatically, but keep in mind that in the first run, the returned
|
241
|
+
hash will be empty.
|
242
|
+
|
243
|
+
def text_size_with_rotation
|
244
|
+
t.stroke_rect(0,0,1,1)
|
245
|
+
t.rescale(0.5)
|
246
|
+
|
247
|
+
equation = '\int_{-\infty}^{\infty} \! e^{-x^{2}}\, \! dx = \sqrt{\pi}'
|
248
|
+
text = "\\fbox{$\\displaystyle #{equation}$}"
|
249
|
+
|
250
|
+
nb = 5
|
251
|
+
nb.times do |i|
|
252
|
+
scale = 0.5 + i * 0.2
|
253
|
+
angle = i * 37
|
254
|
+
x = (i+1)/(nb+1.0)
|
255
|
+
y = x
|
256
|
+
color = [1.0 - i * 0.2, i*0.2, 0]
|
257
|
+
t.show_text('text' => text, 'color' => color, 'x' => x,
|
258
|
+
'y' => x,
|
259
|
+
'alignment' => ALIGNED_AT_MIDHEIGHT,
|
260
|
+
'scale' => scale , 'measure' => "box#{i}",
|
261
|
+
'angle' => angle )
|
262
|
+
size = t.get_text_size("box#{i}")
|
263
|
+
if size.key? 'points'
|
264
|
+
xs = Dvector.new
|
265
|
+
ys = Dvector.new
|
266
|
+
for x,y in size['points']
|
267
|
+
xs << t.convert_output_to_figure_x(x)
|
268
|
+
ys << t.convert_output_to_figure_y(y)
|
269
|
+
end
|
270
|
+
t.stroke_color = color
|
271
|
+
t.line_type = Line_Type_Dashes
|
272
|
+
t.stroke_rect(xs.min, ys.min,
|
273
|
+
(xs.max - xs.min),(ys.max - ys.min))
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
link:images/Text_size_with_rotation.png
|
279
|
+
|
280
|
+
=end
|
281
|
+
|
282
|
+
def get_text_size(name)
|
283
|
+
end
|
284
|
+
|
207
285
|
# Changes the default_text_scale attribute by multiplying it times _scale_.
|
208
286
|
# This also updates the default_text_height_dx and default_text_height_dy
|
209
287
|
# attributes to match the new setting for default_text_scale.
|
@@ -152,6 +152,20 @@ module Tioga
|
|
152
152
|
% personnaly doubt it would really come in useful ;-)...
|
153
153
|
\newcommand\tiogasetfont{\reset@font\SetTiogaFontInfo%
|
154
154
|
\selectfont}%
|
155
|
+
|
156
|
+
|
157
|
+
% This commands typesets its second argument while sending to the
|
158
|
+
% standard output successively the width, height and depth of the
|
159
|
+
% box produced.
|
160
|
+
%
|
161
|
+
% These informations are collected when Tioga runs pdflatex.
|
162
|
+
\newlength{\tiogatempdim}
|
163
|
+
\newcommand{\tiogameasure}[2]{%
|
164
|
+
\settowidth{\tiogatempdim}{#2}\typeout{#1[0]=\the\tiogatempdim}%
|
165
|
+
\settoheight{\tiogatempdim}{#2}\typeout{#1[1]=\the\tiogatempdim}%
|
166
|
+
\settodepth{\tiogatempdim}{#2}\typeout{#1[2]=\the\tiogatempdim}%
|
167
|
+
{#2}}
|
168
|
+
|
155
169
|
\makeatother
|
156
170
|
End_of_preamble
|
157
171
|
COLOR_PREAMBLE = <<'End_of_preamble'
|
data/split/Tioga/lib/Utils.rb
CHANGED
@@ -54,7 +54,7 @@ module Tioga
|
|
54
54
|
}
|
55
55
|
|
56
56
|
# Returns the value of the given TeX dimension in postscript points.
|
57
|
-
def tex_dimension_to_bp(dim)
|
57
|
+
def self.tex_dimension_to_bp(dim)
|
58
58
|
for unit, val in DIMENSION_CONVERSION
|
59
59
|
if dim =~ /^\s*([\d.]+)\s*#{unit}$/
|
60
60
|
return $1.to_f * val
|
@@ -69,6 +69,10 @@ module Tioga
|
|
69
69
|
raise "'#{dim}' is not a valid TeX dimension"
|
70
70
|
end
|
71
71
|
|
72
|
+
def tex_dimension_to_bp(dim)
|
73
|
+
return Utils::tex_dimension_to_bp(dim)
|
74
|
+
end
|
75
|
+
|
72
76
|
|
73
77
|
end
|
74
78
|
end
|
data/split/Tioga/pdfs.h
CHANGED
@@ -24,18 +24,9 @@
|
|
24
24
|
|
25
25
|
#include <namespace.h>
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
extern
|
30
|
-
extern ID save_dir_ID, model_number_ID, add_model_number_ID, quiet_mode_ID;
|
31
|
-
extern ID tex_preview_documentclass_ID, tex_preview_preamble_ID, tex_preview_pagestyle_ID;
|
32
|
-
extern ID tex_preview_left_margin_ID, tex_preview_right_margin_ID, tex_preview_top_margin_ID;
|
33
|
-
extern ID tex_preview_bottom_margin_ID, tex_preview_left_fudge_ID, tex_preview_top_fudge_ID;
|
34
|
-
extern ID do_cmd_ID, data_dir_ID, initialized_ID, tex_xoffset_ID, tex_yoffset_ID;
|
35
|
-
|
36
|
-
extern long int *obj_offsets, capacity_obj_offsets, stream_start, stream_end, length_offset, xref_offset;
|
37
|
-
extern int num_objects, next_available_object_number, next_available_gs_number, next_available_xo_number;
|
38
|
-
extern int next_available_shade_number, next_available_font_number;
|
27
|
+
extern long *obj_offsets, capacity_obj_offsets, stream_start, stream_end, length_offset, xref_offset;
|
28
|
+
extern long num_objects, next_available_object_number, next_available_gs_number, next_available_xo_number;
|
29
|
+
extern long next_available_shade_number, next_available_font_number;
|
39
30
|
extern void Record_Object_Offset(int obj_number);
|
40
31
|
extern char *predefined_Fonts[];
|
41
32
|
extern int num_pdf_standard_fonts, num_predefined_fonts;
|
@@ -75,6 +66,8 @@ typedef struct jpg_info {
|
|
75
66
|
int mask_obj_num;
|
76
67
|
char *filename;
|
77
68
|
} JPG_Info;
|
69
|
+
extern void Write_JPG(JPG_Info *xo, int *ierr);
|
70
|
+
extern void Free_JPG(JPG_Info *xo);
|
78
71
|
|
79
72
|
typedef struct sampled_info {
|
80
73
|
// start must match start of xobj_info
|
@@ -96,6 +89,8 @@ typedef struct sampled_info {
|
|
96
89
|
int lookup_len;
|
97
90
|
unsigned char *lookup;
|
98
91
|
} Sampled_Info;
|
92
|
+
extern void Write_Sampled(Sampled_Info *xo, int *ierr);
|
93
|
+
extern void Free_Sampled(Sampled_Info *xo);
|
99
94
|
|
100
95
|
#define JPG_SUBTYPE 1
|
101
96
|
#define SAMPLED_SUBTYPE 2
|
@@ -186,44 +181,11 @@ extern Old_Font_Dictionary *old_font_dictionaries;
|
|
186
181
|
|
187
182
|
#define RADIANS_TO_DEGREES (180.0 / PI)
|
188
183
|
|
189
|
-
extern bool Used_Any_Fonts(void);
|
190
|
-
extern void Clear_Fonts_In_Use_Flags(void);
|
191
|
-
extern void Write_Font_Dictionaries(void);
|
192
|
-
extern void Write_Font_Descriptors(void);
|
193
|
-
extern void Write_Font_Widths(void);
|
194
|
-
extern void Write_Functions(void);
|
195
|
-
extern void Write_Stroke_Opacity_Objects(void);
|
196
|
-
extern void Write_Fill_Opacity_Objects(void);
|
197
|
-
extern void Write_Shadings(void);
|
198
|
-
extern void Write_JPG(JPG_Info *xo);
|
199
|
-
extern void Write_Sampled(Sampled_Info *xo);
|
200
|
-
extern void Free_Stroke_Opacities(void);
|
201
|
-
extern void Free_Shadings();
|
202
|
-
extern void Free_Functions();
|
203
|
-
extern void Free_JPG(JPG_Info *xo);
|
204
|
-
extern void Free_Sampled(Sampled_Info *xo);
|
205
|
-
extern void Free_Fill_Opacities(void);
|
206
|
-
|
207
|
-
extern void c_append_rect(FM *p, double x, double y, double width, double height);
|
208
|
-
extern void c_clip(FM *p);
|
209
|
-
|
210
184
|
extern bool have_current_point, constructing_path, writing_file;
|
211
|
-
extern double bbox_llx, bbox_lly, bbox_urx, bbox_ury;
|
212
185
|
|
213
186
|
extern FILE *OF; // for the PDF file
|
214
187
|
extern FILE *TF; // for the temp file holding the uncompressed stream
|
215
188
|
|
216
|
-
extern void Unpack_RGB(VALUE rgb, double *rp, double *gp, double *bp);
|
217
|
-
|
218
|
-
extern void Start_Axis_Standard_State(FM *p, VALUE color, double line_width);
|
219
|
-
extern void End_Axis_Standard_State(void);
|
220
|
-
|
221
|
-
extern void Write_gsave(void);
|
222
|
-
extern void Write_grestore(void);
|
223
|
-
|
224
|
-
extern void c_private_set_default_font_size(FM *p, double size);
|
225
|
-
|
226
|
-
void Init_Font_Dictionary(void);
|
227
189
|
|
228
190
|
#endif /* __pdfs_H__ */
|
229
191
|
|
@@ -25,22 +25,24 @@ typedef struct {
|
|
25
25
|
int type;
|
26
26
|
int other_axis_type;
|
27
27
|
double line_width;
|
28
|
-
|
28
|
+
double stroke_color_R;
|
29
|
+
double stroke_color_G;
|
30
|
+
double stroke_color_B;
|
29
31
|
double major_tick_width; // same units as line_width
|
30
32
|
double minor_tick_width; // same units as line_width
|
31
33
|
double major_tick_length; // in units of numeric label char heights
|
32
34
|
double minor_tick_length; // in units of numeric label char heights
|
33
|
-
bool
|
35
|
+
bool log_vals;
|
34
36
|
bool ticks_inside; // inside frame or toward larger x or y value for specific location
|
35
37
|
bool ticks_outside; // inside frame or toward smaller x or y value for specific location
|
36
38
|
double tick_interval; // set to 0 to use default
|
37
39
|
double min_between_major_ticks; // in units of numeric label char heights
|
38
40
|
int number_of_minor_intervals; // set to 0 to use default
|
39
|
-
|
40
|
-
|
41
|
+
OBJ_PTR locations_for_major_ticks; // set to nil to use defaults
|
42
|
+
OBJ_PTR locations_for_minor_ticks; // set to nil to use defaults
|
41
43
|
bool use_fixed_pt;
|
42
44
|
int digits_max;
|
43
|
-
|
45
|
+
OBJ_PTR tick_labels; // set to nil to use defaults
|
44
46
|
double numeric_label_scale;
|
45
47
|
double numeric_label_shift; // in char heights, positive for out from edge (or toward larger x or y value)
|
46
48
|
double numeric_label_angle;
|
@@ -65,62 +67,62 @@ typedef struct {
|
|
65
67
|
int location;
|
66
68
|
} PlotAxis;
|
67
69
|
|
68
|
-
static void
|
69
|
-
s->free_majors = s->free_strings_for_labels = false;
|
70
|
-
s->stroke_color = s->locations_for_major_ticks = s->locations_for_minor_ticks = s->tick_labels = Qnil;
|
71
|
-
s->majors = NULL;
|
72
|
-
s->labels = NULL;
|
73
|
-
}
|
74
|
-
|
75
|
-
static void axis_stroke(FM *p);
|
76
|
-
void figure_moveto(FM *p, double x, double y) // figure coords
|
70
|
+
static void figure_moveto(OBJ_PTR fmkr, FM *p, double x, double y, int *ierr) // figure coords
|
77
71
|
{
|
78
|
-
c_moveto(p, convert_figure_to_output_x(p,x), convert_figure_to_output_y(p,y));
|
72
|
+
c_moveto(fmkr, p, convert_figure_to_output_x(p,x), convert_figure_to_output_y(p,y), ierr);
|
79
73
|
}
|
80
74
|
|
81
|
-
void figure_lineto(FM *p, double x, double y) // figure coords
|
75
|
+
static void figure_lineto(OBJ_PTR fmkr, FM *p, double x, double y, int *ierr) // figure coords
|
82
76
|
{
|
83
|
-
c_lineto(p, convert_figure_to_output_x(p,x), convert_figure_to_output_y(p,y));
|
77
|
+
c_lineto(fmkr, p, convert_figure_to_output_x(p,x), convert_figure_to_output_y(p,y), ierr);
|
84
78
|
}
|
85
79
|
|
86
|
-
void figure_join(FM *p,
|
80
|
+
static void figure_join(OBJ_PTR fmkr, FM *p,
|
81
|
+
double x0, double y0, double x1, double y1, int *ierr) // figure coords
|
87
82
|
{
|
88
|
-
figure_moveto(p, x0, y0);
|
89
|
-
figure_lineto(p, x1, y1);
|
83
|
+
figure_moveto(fmkr, p, x0, y0, ierr);
|
84
|
+
figure_lineto(fmkr, p, x1, y1, ierr);
|
90
85
|
}
|
91
86
|
|
92
|
-
static void axis_stroke(FM *p)
|
87
|
+
static void axis_stroke(OBJ_PTR fmkr, FM *p, int *ierr)
|
93
88
|
{
|
94
|
-
|
89
|
+
c_stroke(fmkr,p, ierr);
|
95
90
|
}
|
96
91
|
|
97
|
-
void figure_join_and_stroke(FM *p,
|
92
|
+
static void figure_join_and_stroke(OBJ_PTR fmkr, FM *p,
|
93
|
+
double x0, double y0, double x1, double y1, int *ierr) // figure coords
|
98
94
|
{
|
99
|
-
figure_join(p, x0, y0, x1, y1);
|
100
|
-
|
95
|
+
figure_join(fmkr, p, x0, y0, x1, y1, ierr);
|
96
|
+
c_stroke(fmkr,p, ierr);
|
101
97
|
}
|
102
98
|
|
103
|
-
static void Get_xaxis_Specs(FM *p, PlotAxis *s)
|
99
|
+
static void Get_xaxis_Specs(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
|
104
100
|
{
|
101
|
+
s->free_majors = s->free_strings_for_labels = false;
|
102
|
+
s->stroke_color_R = 0.0; s->stroke_color_G = 0.0; s->stroke_color_B = 0.0;
|
103
|
+
s->majors = NULL;
|
104
|
+
s->labels = NULL;
|
105
105
|
s->type = p->xaxis_type;
|
106
106
|
s->other_axis_type = p->yaxis_type;
|
107
107
|
s->line_width = p->xaxis_line_width; // for axis line
|
108
|
-
s->
|
108
|
+
s->stroke_color_R = p->xaxis_stroke_color_R; // for axis line and tick marks
|
109
|
+
s->stroke_color_G = p->xaxis_stroke_color_G;
|
110
|
+
s->stroke_color_B = p->xaxis_stroke_color_B;
|
109
111
|
s->major_tick_width = p->xaxis_major_tick_width; // same units as line_width
|
110
112
|
s->minor_tick_width = p->xaxis_minor_tick_width; // same units as line_width
|
111
113
|
s->major_tick_length = p->xaxis_major_tick_length; // in units of numeric label char heights
|
112
114
|
s->minor_tick_length = p->xaxis_minor_tick_length; // in units of numeric label char heights
|
113
|
-
s->
|
115
|
+
s->log_vals = p->xaxis_log_values;
|
114
116
|
s->ticks_inside = p->xaxis_ticks_inside; // inside frame or toward larger x or y value for specific location
|
115
117
|
s->ticks_outside = p->xaxis_ticks_outside; // inside frame or toward smaller x or y value for specific location
|
116
118
|
s->tick_interval = p->xaxis_tick_interval; // set to 0 to use default
|
117
119
|
s->min_between_major_ticks = p->xaxis_min_between_major_ticks; // in units of numeric label char heights
|
118
|
-
s->number_of_minor_intervals = p->xaxis_number_of_minor_intervals; // set to 0 to use default
|
119
|
-
s->locations_for_major_ticks =
|
120
|
-
s->locations_for_minor_ticks =
|
120
|
+
s->number_of_minor_intervals = p->xaxis_number_of_minor_intervals; // set to 0 to use default
|
121
|
+
s->locations_for_major_ticks = Get_xaxis_locations_for_major_ticks(fmkr, ierr);
|
122
|
+
s->locations_for_minor_ticks = Get_xaxis_locations_for_minor_ticks(fmkr, ierr);
|
121
123
|
s->use_fixed_pt = p->xaxis_use_fixed_pt;
|
122
124
|
s->digits_max = p->xaxis_digits_max;
|
123
|
-
s->tick_labels =
|
125
|
+
s->tick_labels = Get_xaxis_tick_labels(fmkr, ierr);
|
124
126
|
s->numeric_label_decimal_digits = p->xaxis_numeric_label_decimal_digits; // set to negative to use default
|
125
127
|
s->numeric_label_scale = p->xaxis_numeric_label_scale;
|
126
128
|
s->numeric_label_shift = p->xaxis_numeric_label_shift; // in char heights, positive for out from edge (or toward larger x or y value)
|
@@ -131,27 +133,33 @@ static void Get_xaxis_Specs(FM *p, PlotAxis *s)
|
|
131
133
|
s->numeric_label_phase = p->xaxis_numeric_label_phase;
|
132
134
|
}
|
133
135
|
|
134
|
-
static void Get_yaxis_Specs(FM *p, PlotAxis *s)
|
136
|
+
static void Get_yaxis_Specs(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
|
135
137
|
{
|
138
|
+
s->free_majors = s->free_strings_for_labels = false;
|
139
|
+
s->stroke_color_R = 0.0; s->stroke_color_G = 0.0; s->stroke_color_B = 0.0;
|
140
|
+
s->majors = NULL;
|
141
|
+
s->labels = NULL;
|
136
142
|
s->type = p->yaxis_type;
|
137
143
|
s->other_axis_type = p->xaxis_type;
|
138
144
|
s->line_width = p->yaxis_line_width; // for axis line
|
139
|
-
s->
|
145
|
+
s->stroke_color_R = p->yaxis_stroke_color_R; // for axis line and tick marks
|
146
|
+
s->stroke_color_G = p->yaxis_stroke_color_G;
|
147
|
+
s->stroke_color_B = p->yaxis_stroke_color_B;
|
140
148
|
s->major_tick_width = p->yaxis_major_tick_width; // same units as line_width
|
141
149
|
s->minor_tick_width = p->yaxis_minor_tick_width; // same units as line_width
|
142
150
|
s->major_tick_length = p->yaxis_major_tick_length; // in units of numeric label char heights
|
143
151
|
s->minor_tick_length = p->yaxis_minor_tick_length; // in units of numeric label char heights
|
144
|
-
s->
|
152
|
+
s->log_vals = p->yaxis_log_values;
|
145
153
|
s->ticks_inside = p->yaxis_ticks_inside; // inside frame or toward larger x or y value for specific location
|
146
154
|
s->ticks_outside = p->yaxis_ticks_outside; // inside frame or toward smaller x or y value for specific location
|
147
155
|
s->tick_interval = p->yaxis_tick_interval; // set to 0 to use default
|
148
156
|
s->min_between_major_ticks = p->yaxis_min_between_major_ticks; // in units of numeric label char heights
|
149
|
-
s->number_of_minor_intervals = p->yaxis_number_of_minor_intervals; // set to 0 to use default
|
150
|
-
s->locations_for_major_ticks =
|
151
|
-
s->locations_for_minor_ticks =
|
157
|
+
s->number_of_minor_intervals = p->yaxis_number_of_minor_intervals; // set to 0 to use default
|
158
|
+
s->locations_for_major_ticks = Get_yaxis_locations_for_major_ticks(fmkr, ierr);
|
159
|
+
s->locations_for_minor_ticks = Get_yaxis_locations_for_minor_ticks(fmkr, ierr);
|
160
|
+
s->tick_labels = Get_yaxis_tick_labels(fmkr, ierr);
|
152
161
|
s->use_fixed_pt = p->yaxis_use_fixed_pt;
|
153
162
|
s->digits_max = p->yaxis_digits_max;
|
154
|
-
s->tick_labels = p->yaxis_tick_labels; // set to nil to use defaults. else must have a label for each major tick
|
155
163
|
s->numeric_label_decimal_digits = p->yaxis_numeric_label_decimal_digits; // set to negative to use default
|
156
164
|
s->numeric_label_scale = p->yaxis_numeric_label_scale;
|
157
165
|
s->numeric_label_shift = p->yaxis_numeric_label_shift; // in char heights, positive for out from edge (or toward larger x or y value)
|
@@ -164,7 +172,7 @@ static void Get_yaxis_Specs(FM *p, PlotAxis *s)
|
|
164
172
|
|
165
173
|
/*======================================================================*/
|
166
174
|
|
167
|
-
static void draw_axis_line(FM *p, int location, PlotAxis *s)
|
175
|
+
static void draw_axis_line(OBJ_PTR fmkr, FM *p, int location, PlotAxis *s, int *ierr)
|
168
176
|
{
|
169
177
|
switch (location) {
|
170
178
|
case LEFT:
|
@@ -246,58 +254,58 @@ static void draw_axis_line(FM *p, int location, PlotAxis *s)
|
|
246
254
|
s->top_or_right = false;
|
247
255
|
break;
|
248
256
|
}
|
249
|
-
c_line_width_set(p, s->line_width);
|
250
|
-
figure_join_and_stroke(p, s->x0, s->y0, s->x1, s->y1);
|
257
|
+
c_line_width_set(fmkr, p, s->line_width, ierr);
|
258
|
+
figure_join_and_stroke(fmkr, p, s->x0, s->y0, s->x1, s->y1, ierr);
|
251
259
|
}
|
252
260
|
|
253
|
-
static char *Create_Label(double
|
254
|
-
|
255
|
-
|
256
|
-
|
261
|
+
static char *Create_Label(double val, int scale, int prec,
|
262
|
+
bool log_vals, bool use_fixed_pt, char *postfix, PlotAxis *s, int *ierr)
|
263
|
+
{ // val in figure coords
|
264
|
+
char buff[100], form[100], *string;
|
265
|
+
int exponent = ROUND(val);
|
257
266
|
buff[0] = 0;
|
258
|
-
if (
|
259
|
-
double sav_val =
|
260
|
-
|
267
|
+
if (log_vals && use_fixed_pt) { /* Logarithmic */
|
268
|
+
double sav_val = val, pow_val;
|
269
|
+
val = pow(10.0, exponent);
|
261
270
|
pow_val = pow(10.0, sav_val);
|
262
271
|
if (exponent < 0) {
|
263
|
-
char form[60];
|
264
272
|
int numdig = ABS(exponent)+1;
|
265
|
-
|
266
|
-
|
267
|
-
} else if (abs(
|
268
|
-
|
273
|
+
snprintf(form, sizeof(form), (s->vertical)? "\\tiogayaxisnumericlabel{%%.%df}" : "\\tiogaxaxisnumericlabel{%%.%df}", numdig);
|
274
|
+
snprintf(buff, sizeof(buff), form, pow_val);
|
275
|
+
} else if (abs(val - pow_val) > 0.1) {
|
276
|
+
snprintf(buff, sizeof(buff), (s->vertical)? "\\tiogayaxisnumericlabel{%0.2f}" : "\\tiogaxaxisnumericlabel{%0.2f}", pow_val);
|
269
277
|
} else {
|
270
|
-
|
278
|
+
snprintf(buff, sizeof(buff), (s->vertical)? "\\tiogayaxisnumericlabel{%d}" : "\\tiogaxaxisnumericlabel{%d}", (int) val);
|
271
279
|
}
|
272
|
-
} else if (
|
280
|
+
} else if (log_vals) {
|
273
281
|
/* Exponential, i.e. 10^-1, 1, 10, 10^2, etc */
|
274
|
-
double abs_diff = fabs(
|
275
|
-
if (abs_diff > 0.1)
|
282
|
+
double abs_diff = fabs(val - exponent);
|
283
|
+
if (abs_diff > 0.1) snprintf(buff, sizeof(buff), (s->vertical)? "\\tiogayaxisnumericlabel{10^{%0.1f}}" : "\\tiogaxaxisnumericlabel{10^{%0.1f}}", val);
|
276
284
|
else if (exponent == 0) strcpy(buff, "1");
|
277
285
|
else if (exponent == 1) strcpy(buff, "10");
|
278
|
-
else
|
286
|
+
else snprintf(buff, sizeof(buff), (s->vertical)? "\\tiogayaxisnumericlabel{10^{%d}}" : "\\tiogaxaxisnumericlabel{10^{%d}}", exponent);
|
279
287
|
} else { /* Linear */
|
280
|
-
char form[10];
|
281
288
|
double scale2;
|
282
289
|
int precis = s->numeric_label_decimal_digits; // use this precision if it is >= 0
|
283
290
|
if (precis >= 0) prec = precis;
|
284
|
-
if (scale)
|
291
|
+
if (scale) val /= pow(10.,(double)scale);
|
285
292
|
/* This is necessary to prevent labels like "-0.0" on some systems */
|
286
293
|
scale2 = pow(10., prec);
|
287
|
-
|
288
|
-
|
289
|
-
|
294
|
+
val = floor((val * scale2) + .5) / scale2;
|
295
|
+
snprintf(form, sizeof(form), (s->vertical)? "\\tiogayaxisnumericlabel{%%.%df}" : "\\tiogaxaxisnumericlabel{%%.%df}", (int) prec);
|
296
|
+
snprintf(buff, sizeof(buff), form, val);
|
290
297
|
}
|
291
298
|
int len = strlen(buff);
|
292
299
|
if (postfix != NULL) { strcpy(buff+len, postfix); len = strlen(buff); }
|
293
|
-
string =
|
300
|
+
string = ALLOC_N_char(len+1);
|
294
301
|
strcpy(string, buff);
|
295
302
|
return string;
|
296
303
|
}
|
297
304
|
|
298
|
-
char *Get_String(
|
299
|
-
|
300
|
-
|
305
|
+
char *Get_String(OBJ_PTR ary, int index, int *ierr) {
|
306
|
+
OBJ_PTR s = Array_Entry(ary,index,ierr);
|
307
|
+
if (*ierr != 0) return NULL;
|
308
|
+
return String_Ptr(s,ierr);
|
301
309
|
}
|
302
310
|
|
303
311
|
#define MAX_FIXDIG_POS 6
|
@@ -305,7 +313,7 @@ char *Get_String(VALUE ary, int index) {
|
|
305
313
|
#define DIGMAX_DEF 6
|
306
314
|
|
307
315
|
static void Pick_Label_Precision(double vmin, double vmax, double tick, bool use_fixed_pt,
|
308
|
-
int *mode, int *prec, int digmax, int *scale) {
|
316
|
+
int *mode, int *prec, int digmax, int *scale, int *ierr) {
|
309
317
|
double chosen, notchosen, vmod, t0, shifted;
|
310
318
|
int msd, notmsd, np, digmin, digfix;
|
311
319
|
*mode = *scale = 0;
|
@@ -383,23 +391,25 @@ static void Pick_Label_Precision(double vmin, double vmax, double tick, bool use
|
|
383
391
|
|
384
392
|
}
|
385
393
|
|
386
|
-
static char **Get_Labels(FM *p, PlotAxis *s)
|
394
|
+
static char **Get_Labels(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
|
387
395
|
{
|
388
|
-
char **labels = (char **)
|
396
|
+
char **labels = (char **)ALLOC_N_pointer(s->nmajors);
|
389
397
|
char postfix[50], *ps;
|
390
398
|
int i, k, j;
|
391
399
|
k = s->numeric_label_frequency;
|
392
400
|
j = s->numeric_label_phase;
|
393
|
-
if (s->tick_labels==
|
401
|
+
if (s->tick_labels==OBJ_NIL) { // create label strings
|
394
402
|
int mode, prec, scale;
|
395
|
-
Pick_Label_Precision(s->axis_min, s->axis_max, s->interval,
|
403
|
+
Pick_Label_Precision(s->axis_min, s->axis_max, s->interval,
|
404
|
+
s->use_fixed_pt, &mode, &prec, s->digits_max, &scale, ierr);
|
405
|
+
if (*ierr != 0) return NULL;
|
396
406
|
int i;
|
397
407
|
int upper_right = (s->reversed)? 0 : s->nmajors-1;
|
398
408
|
int lower_left = (s->reversed)? s->nmajors-1 : 0;
|
399
409
|
for (i = 0; i < s->nmajors; i++) {
|
400
410
|
ps = NULL;
|
401
|
-
if (i == upper_right && !s->
|
402
|
-
|
411
|
+
if (i == upper_right && !s->log_vals && mode && scale)
|
412
|
+
snprintf(ps = postfix, sizeof(postfix),
|
403
413
|
(s->vertical)? "$\\times$\\tiogayaxisnumericlabel{10^{%d}}" : "$\\times$\\tiogaxaxisnumericlabel{10^{%d}}",
|
404
414
|
scale);
|
405
415
|
if ((i+j) % k != 0) {
|
@@ -410,23 +420,29 @@ static char **Get_Labels(FM *p, PlotAxis *s)
|
|
410
420
|
s->other_axis_type == AXIS_WITH_TICKS_AND_NUMERIC_LABELS)) {
|
411
421
|
labels[i] = NULL;
|
412
422
|
} else {
|
413
|
-
labels[i] = Create_Label(s->majors[i], scale, prec, s->
|
423
|
+
labels[i] = Create_Label(s->majors[i], scale, prec, s->log_vals, s->use_fixed_pt, ps, s, ierr);
|
424
|
+
if (*ierr != 0) return NULL;
|
414
425
|
}
|
415
426
|
}
|
416
427
|
s->free_strings_for_labels = true;
|
417
428
|
} else { // use the given label strings
|
418
|
-
|
419
|
-
if (
|
420
|
-
|
429
|
+
int len = Array_Len(s->tick_labels,ierr);
|
430
|
+
if (*ierr != 0) return NULL;
|
431
|
+
if (len != s->nmajors) {
|
432
|
+
RAISE_ERROR("Sorry: must have same number of labels as major ticks", ierr);
|
433
|
+
return NULL;
|
434
|
+
}
|
421
435
|
for (i = 0; i < s->nmajors; i++) {
|
422
|
-
labels[i] = Get_String(
|
436
|
+
labels[i] = Get_String(s->tick_labels, i, ierr);
|
437
|
+
if (*ierr != 0) return NULL;
|
423
438
|
}
|
424
439
|
s->free_strings_for_labels = false;
|
425
440
|
}
|
426
441
|
return labels;
|
427
442
|
}
|
428
443
|
|
429
|
-
static double *Pick_Locations_for_Major_Ticks(double interval,
|
444
|
+
static double *Pick_Locations_for_Major_Ticks(double interval,
|
445
|
+
double axis_min, double axis_max, int *num_locations, int *ierr)
|
430
446
|
{
|
431
447
|
double next_tick, prev_tick, starting_tick;
|
432
448
|
double *majors;
|
@@ -445,7 +461,7 @@ static double *Pick_Locations_for_Major_Ticks(double interval, double axis_min,
|
|
445
461
|
if (nmajors > 1) break;
|
446
462
|
interval *= 0.5;
|
447
463
|
}
|
448
|
-
majors =
|
464
|
+
majors = ALLOC_N_double(nmajors);
|
449
465
|
prev_tick = starting_tick;
|
450
466
|
for (i=0; i < nmajors; i++) {
|
451
467
|
majors[i] = prev_tick += interval;
|
@@ -454,7 +470,7 @@ static double *Pick_Locations_for_Major_Ticks(double interval, double axis_min,
|
|
454
470
|
return majors;
|
455
471
|
}
|
456
472
|
|
457
|
-
static int Pick_Number_of_Minor_Intervals(double length)
|
473
|
+
static int Pick_Number_of_Minor_Intervals(double length, int *ierr)
|
458
474
|
{
|
459
475
|
double t1, fuzz, newlen;
|
460
476
|
int np, num_subintervals, inewlen;
|
@@ -482,7 +498,8 @@ static int Pick_Number_of_Minor_Intervals(double length)
|
|
482
498
|
return num_subintervals;
|
483
499
|
}
|
484
500
|
|
485
|
-
static void Pick_Major_Tick_Interval(FM *p,
|
501
|
+
static void Pick_Major_Tick_Interval(OBJ_PTR fmkr, FM *p,
|
502
|
+
double tick_min, double tick_gap, double length, bool log_vals, double *tick, int *ierr)
|
486
503
|
{
|
487
504
|
double t1, t2, tick_reasonable, base_interval;
|
488
505
|
int np, i;
|
@@ -497,7 +514,7 @@ static void Pick_Major_Tick_Interval(FM *p, double tick_min, double tick_gap, do
|
|
497
514
|
else if (t1 > 1.5) { t2 = 5.0; np--; }
|
498
515
|
else { t2 = 2.0; np--; }
|
499
516
|
/* Now compute reasonable tick spacing */
|
500
|
-
if (
|
517
|
+
if (log_vals) {
|
501
518
|
tick_reasonable = 1.0;
|
502
519
|
} else {
|
503
520
|
base_interval = pow(10.0, (double) np);
|
@@ -513,17 +530,19 @@ static void Pick_Major_Tick_Interval(FM *p, double tick_min, double tick_gap, do
|
|
513
530
|
else { // check the given interval compared to the default
|
514
531
|
*tick = ABS(*tick);
|
515
532
|
if(*tick < 1.e-4*tick_reasonable) {
|
516
|
-
|
533
|
+
RAISE_ERROR_g("Sorry: magnitude of specified tick interval (%g) is too small", *tick, ierr);
|
534
|
+
return;
|
517
535
|
}
|
518
536
|
}
|
519
537
|
}
|
520
538
|
|
521
|
-
static void draw_major_ticks(FM *p, PlotAxis *s)
|
539
|
+
static void draw_major_ticks(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
|
522
540
|
{
|
523
541
|
s->num_minors = s->number_of_minor_intervals;
|
524
|
-
if (s->locations_for_major_ticks !=
|
542
|
+
if (s->locations_for_major_ticks != OBJ_NIL) {
|
525
543
|
long len;
|
526
|
-
s->majors =
|
544
|
+
s->majors = Vector_Data_for_Read(s->locations_for_major_ticks, &len, ierr);
|
545
|
+
if (*ierr != 0) return;
|
527
546
|
s->nmajors = len;
|
528
547
|
if (len > 1) {
|
529
548
|
s->interval = s->majors[1] - s->majors[0];
|
@@ -534,8 +553,10 @@ static void draw_major_ticks(FM *p, PlotAxis *s)
|
|
534
553
|
double height = ((s->vertical)? p->default_text_height_dy : p->default_text_height_dx);
|
535
554
|
double tick_min = s->min_between_major_ticks * height;
|
536
555
|
double tick_gap = 10.0 * height;
|
537
|
-
Pick_Major_Tick_Interval(p, tick_min, tick_gap, s->length, s->
|
538
|
-
|
556
|
+
Pick_Major_Tick_Interval(fmkr, p, tick_min, tick_gap, s->length, s->log_vals, &s->interval, ierr);
|
557
|
+
if (*ierr != 0) return;
|
558
|
+
s->majors = Pick_Locations_for_Major_Ticks(s->interval, s->axis_min, s->axis_max, &s->nmajors, ierr);
|
559
|
+
if (*ierr != 0) return;
|
539
560
|
s->free_majors = true;
|
540
561
|
}
|
541
562
|
int i;
|
@@ -545,51 +566,64 @@ static void draw_major_ticks(FM *p, PlotAxis *s)
|
|
545
566
|
if (s->ticks_inside) inside = length;
|
546
567
|
if (s->ticks_outside) outside = length;
|
547
568
|
if (s->top_or_right) { inside = -inside; outside = -outside; }
|
548
|
-
if (s->line_width != s->major_tick_width)
|
549
|
-
c_line_width_set(p, s->line_width = s->major_tick_width);
|
569
|
+
if (s->line_width != s->major_tick_width) {
|
570
|
+
c_line_width_set(fmkr, p, s->line_width = s->major_tick_width, ierr);
|
571
|
+
if (*ierr != 0) return;
|
572
|
+
}
|
550
573
|
for (i=0; i < s->nmajors; i++) {
|
551
574
|
if (s->vertical)
|
552
|
-
figure_join(p, s->x0+inside, s->majors[i], s->x0+outside, s->majors[i]);
|
575
|
+
figure_join(fmkr, p, s->x0+inside, s->majors[i], s->x0+outside, s->majors[i], ierr);
|
553
576
|
else
|
554
|
-
figure_join(p, s->majors[i], s->y0+inside, s->majors[i], s->y0+outside);
|
577
|
+
figure_join(fmkr, p, s->majors[i], s->y0+inside, s->majors[i], s->y0+outside, ierr);
|
555
578
|
did_line = true;
|
579
|
+
if (*ierr != 0) return;
|
556
580
|
}
|
557
|
-
if (did_line) axis_stroke(p);
|
581
|
+
if (did_line) axis_stroke(fmkr,p, ierr);
|
558
582
|
}
|
559
583
|
|
560
|
-
static
|
561
|
-
{
|
562
|
-
0.301030, 0.477121, 0.602060, 0.698970,
|
563
|
-
0.778151, 0.845098, 0.903090, 0.954243
|
564
|
-
};
|
565
|
-
|
566
|
-
static void draw_minor_ticks(FM *p, PlotAxis *s)
|
584
|
+
static void draw_minor_ticks(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
|
567
585
|
{
|
568
586
|
if (s->number_of_minor_intervals <= 0) {
|
569
|
-
if (s->
|
587
|
+
if (s->log_vals) {
|
570
588
|
double interval = s->majors[1] - s->majors[0];
|
571
589
|
s->number_of_minor_intervals = (abs(interval) != 1.0 || s->nmajors > 10)? 1 : 9;
|
572
|
-
} else
|
590
|
+
} else {
|
591
|
+
s->number_of_minor_intervals = Pick_Number_of_Minor_Intervals(s->interval, ierr);
|
592
|
+
if (*ierr != 0) return;
|
593
|
+
}
|
573
594
|
}
|
574
595
|
int i, j, nsub = s->number_of_minor_intervals;
|
575
596
|
double inside=0.0, outside=0.0, length;
|
576
597
|
bool did_line = false;
|
577
|
-
|
598
|
+
double log_subintervals[8];
|
599
|
+
log_subintervals[0] = 0.301030;
|
600
|
+
log_subintervals[1] = 0.477121;
|
601
|
+
log_subintervals[2] = 0.602060;
|
602
|
+
log_subintervals[3] = 0.698970;
|
603
|
+
log_subintervals[4] = 0.778151;
|
604
|
+
log_subintervals[5] = 0.845098;
|
605
|
+
log_subintervals[6] = 0.903090;
|
606
|
+
log_subintervals[7] = 0.954243;
|
607
|
+
if (s->log_vals && nsub > 9) nsub = 9;
|
578
608
|
length = s->minor_tick_length * ((s->vertical)? p->default_text_height_dx : p->default_text_height_dy);
|
579
609
|
if (s->ticks_inside) inside = length;
|
580
610
|
if (s->ticks_outside) outside = length;
|
581
611
|
if (s->top_or_right) { inside = -inside; outside = -outside; }
|
582
|
-
if (s->line_width != s->minor_tick_width)
|
583
|
-
c_line_width_set(p, s->line_width = s->minor_tick_width);
|
584
|
-
|
612
|
+
if (s->line_width != s->minor_tick_width) {
|
613
|
+
c_line_width_set(fmkr, p, s->line_width = s->minor_tick_width, ierr);
|
614
|
+
if (*ierr != 0) return;
|
615
|
+
}
|
616
|
+
if (s->locations_for_minor_ticks != OBJ_NIL) {
|
585
617
|
long cnt;
|
586
|
-
double *locs =
|
618
|
+
double *locs = Vector_Data_for_Read(s->locations_for_minor_ticks, &cnt, ierr);
|
619
|
+
if (*ierr != 0) return;
|
587
620
|
for (i=0; i < cnt; i++) {
|
588
621
|
if (s->vertical)
|
589
|
-
figure_join(p, s->x0+inside, locs[i], s->x0+outside, locs[i]);
|
622
|
+
figure_join(fmkr, p, s->x0+inside, locs[i], s->x0+outside, locs[i], ierr);
|
590
623
|
else
|
591
|
-
figure_join(p, locs[i], s->y0+inside, locs[i], s->y0+outside);
|
624
|
+
figure_join(fmkr, p, locs[i], s->y0+inside, locs[i], s->y0+outside, ierr);
|
592
625
|
did_line = true;
|
626
|
+
if (*ierr != 0) return;
|
593
627
|
}
|
594
628
|
} else {
|
595
629
|
for (i=0; i <= s->nmajors; i++) {
|
@@ -598,54 +632,66 @@ static void draw_minor_ticks(FM *p, PlotAxis *s)
|
|
598
632
|
double subinterval = (next_loc - loc) / nsub;
|
599
633
|
if (subinterval <= 0.0) continue;
|
600
634
|
for (j = 1; j < nsub; j++) {
|
601
|
-
double subloc = loc + ((!s->
|
635
|
+
double subloc = loc + ((!s->log_vals) ? (j * subinterval) : log_subintervals[j-1]);
|
602
636
|
if (subloc >= next_loc) break;
|
603
637
|
if (subloc <= s->axis_min || subloc >= s->axis_max) continue;
|
604
638
|
if (s->vertical)
|
605
|
-
figure_join(p, s->x0+inside, subloc, s->x0+outside, subloc);
|
639
|
+
figure_join(fmkr, p, s->x0+inside, subloc, s->x0+outside, subloc, ierr);
|
606
640
|
else
|
607
|
-
figure_join(p, subloc, s->y0+inside, subloc, s->y0+outside);
|
641
|
+
figure_join(fmkr, p, subloc, s->y0+inside, subloc, s->y0+outside, ierr);
|
608
642
|
did_line = true;
|
643
|
+
if (*ierr != 0) return;
|
609
644
|
}
|
610
645
|
}
|
611
646
|
}
|
612
|
-
if (did_line) axis_stroke(p);
|
647
|
+
if (did_line) axis_stroke(fmkr,p, ierr);
|
613
648
|
}
|
614
649
|
|
615
|
-
static void show_numeric_label(FM *p
|
650
|
+
static void show_numeric_label(OBJ_PTR fmkr, FM *p, PlotAxis *s,
|
651
|
+
char *text, int location, double position, double shift, int *ierr)
|
616
652
|
{ // position is in figure coords and must be converted to frame coords
|
617
653
|
double pos = ((!s->reversed)? (position - s->axis_min) : (s->axis_max - position)) / s->length;
|
618
|
-
c_show_rotated_text(p, text, location, shift, pos,
|
619
|
-
|
654
|
+
c_show_rotated_text(fmkr, p, text, location, shift, pos,
|
655
|
+
s->numeric_label_scale, s->numeric_label_angle, s->numeric_label_justification, s->numeric_label_alignment, OBJ_NIL, ierr);
|
620
656
|
}
|
621
657
|
|
622
|
-
static void draw_numeric_labels(FM *p
|
658
|
+
static void draw_numeric_labels(OBJ_PTR fmkr, FM *p, int location, PlotAxis *s, int *ierr)
|
623
659
|
{
|
624
660
|
int i;
|
625
661
|
double shift = (s->ticks_outside) ? s->major_tick_length : 0.5; // default shift
|
626
662
|
shift += s->numeric_label_shift;
|
627
|
-
s->labels = Get_Labels(p, s);
|
663
|
+
s->labels = Get_Labels(fmkr, p, s, ierr);
|
628
664
|
for (i=0; i < s->nmajors; i++) {
|
629
|
-
if (s->labels[i] != NULL)
|
665
|
+
if (s->labels[i] != NULL) {
|
666
|
+
show_numeric_label(fmkr, p, s, s->labels[i], location, s->majors[i], shift, ierr);
|
667
|
+
if (*ierr != 0) return;
|
668
|
+
}
|
630
669
|
}
|
631
670
|
}
|
632
671
|
|
633
|
-
static void c_show_side(
|
672
|
+
static void c_show_side(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr) {
|
634
673
|
int i;
|
635
674
|
if (s->type == AXIS_HIDDEN) return;
|
636
|
-
Start_Axis_Standard_State(
|
637
|
-
|
638
|
-
|
675
|
+
Start_Axis_Standard_State(fmkr, p,
|
676
|
+
s->stroke_color_R, s->stroke_color_G, s->stroke_color_B,
|
677
|
+
s->line_width * p->default_line_scale, ierr);
|
678
|
+
if (*ierr != 0) return;
|
679
|
+
draw_axis_line(fmkr, p, s->location, s, ierr);
|
680
|
+
if (*ierr != 0) return;
|
639
681
|
if (s->type == AXIS_LINE_ONLY) goto done;
|
640
|
-
draw_major_ticks(p, s);
|
682
|
+
draw_major_ticks(fmkr, p, s, ierr);
|
683
|
+
if (*ierr != 0) return;
|
641
684
|
if (s->type == AXIS_WITH_MAJOR_TICKS_ONLY) goto done;
|
642
685
|
if (s->type == AXIS_WITH_MAJOR_TICKS_AND_NUMERIC_LABELS) {
|
643
|
-
draw_numeric_labels(
|
686
|
+
draw_numeric_labels(fmkr, p, s->location, s, ierr);
|
687
|
+
if (*ierr != 0) return;
|
644
688
|
goto done;
|
645
689
|
}
|
646
|
-
draw_minor_ticks(p, s);
|
690
|
+
draw_minor_ticks(fmkr, p, s, ierr);
|
691
|
+
if (*ierr != 0) return;
|
647
692
|
if (s->type == AXIS_WITH_TICKS_ONLY) goto done;
|
648
|
-
draw_numeric_labels(
|
693
|
+
draw_numeric_labels(fmkr, p, s->location, s, ierr);
|
694
|
+
if (*ierr != 0) return;
|
649
695
|
done:
|
650
696
|
End_Axis_Standard_State(); // grestore
|
651
697
|
if (s->free_majors) free(s->majors);
|
@@ -658,128 +704,95 @@ static void c_show_side(VALUE fmkr, FM *p, PlotAxis *s) {
|
|
658
704
|
}
|
659
705
|
}
|
660
706
|
|
661
|
-
|
707
|
+
|
708
|
+
void c_show_axis(OBJ_PTR fmkr, FM *p, int location, int *ierr)
|
662
709
|
{
|
663
|
-
FM *p = Get_FM(fmkr);
|
664
710
|
PlotAxis axis;
|
665
|
-
int location;
|
666
|
-
Init_PlotAxis_struct(&axis);
|
667
|
-
loc = rb_Integer(loc);
|
668
|
-
location = NUM2INT(loc);
|
669
711
|
if (location == LEFT || location == RIGHT || location == AT_X_ORIGIN) {
|
670
|
-
if (!p->yaxis_visible)
|
671
|
-
Get_yaxis_Specs(p, &axis);
|
712
|
+
if (!p->yaxis_visible) return;
|
713
|
+
Get_yaxis_Specs(fmkr, p, &axis, ierr);
|
672
714
|
} else if (location == TOP || location == BOTTOM || location == AT_Y_ORIGIN) {
|
673
|
-
if (!p->xaxis_visible)
|
674
|
-
Get_xaxis_Specs(p, &axis);
|
675
|
-
} else
|
676
|
-
"Sorry: invalid 'loc' for axis: must be one of LEFT, RIGHT, TOP, BOTTOM, AT_X_ORIGIN, or AT_Y_ORIGIN: is (%i)", location);
|
715
|
+
if (!p->xaxis_visible) return;
|
716
|
+
Get_xaxis_Specs(fmkr, p, &axis, ierr);
|
717
|
+
} else RAISE_ERROR_i(
|
718
|
+
"Sorry: invalid 'loc' for axis: must be one of LEFT, RIGHT, TOP, BOTTOM, AT_X_ORIGIN, or AT_Y_ORIGIN: is (%i)", location, ierr);
|
719
|
+
if (*ierr != 0) return;
|
677
720
|
axis.location = location;
|
678
|
-
c_show_side(fmkr, p, &axis);
|
679
|
-
done:
|
680
|
-
return fmkr;
|
721
|
+
c_show_side(fmkr, p, &axis, ierr);
|
681
722
|
}
|
682
723
|
|
683
|
-
|
684
|
-
|
724
|
+
void c_show_edge(OBJ_PTR fmkr, FM *p, int location, int *ierr)
|
725
|
+
{
|
685
726
|
PlotAxis axis;
|
686
|
-
int location;
|
687
|
-
Init_PlotAxis_struct(&axis);
|
688
|
-
loc = rb_Integer(loc);
|
689
|
-
location = NUM2INT(loc);
|
690
727
|
switch (location) {
|
691
728
|
case LEFT:
|
692
|
-
if (!p->left_edge_visible)
|
693
|
-
Get_yaxis_Specs(p, &axis); axis.type = p->left_edge_type;
|
729
|
+
if (!p->left_edge_visible) return;
|
730
|
+
Get_yaxis_Specs(fmkr, p, &axis, ierr); axis.type = p->left_edge_type;
|
694
731
|
break;
|
695
732
|
case RIGHT:
|
696
|
-
if (!p->right_edge_visible)
|
697
|
-
Get_yaxis_Specs(p, &axis); axis.type = p->right_edge_type;
|
733
|
+
if (!p->right_edge_visible) return;
|
734
|
+
Get_yaxis_Specs(fmkr, p, &axis, ierr); axis.type = p->right_edge_type;
|
698
735
|
break;
|
699
736
|
case BOTTOM:
|
700
|
-
if (!p->bottom_edge_visible)
|
701
|
-
Get_xaxis_Specs(p, &axis); axis.type = p->bottom_edge_type;
|
737
|
+
if (!p->bottom_edge_visible) return;
|
738
|
+
Get_xaxis_Specs(fmkr, p, &axis, ierr); axis.type = p->bottom_edge_type;
|
702
739
|
break;
|
703
740
|
case TOP:
|
704
|
-
if (!p->top_edge_visible)
|
705
|
-
Get_xaxis_Specs(p, &axis); axis.type = p->top_edge_type;
|
741
|
+
if (!p->top_edge_visible) return;
|
742
|
+
Get_xaxis_Specs(fmkr, p, &axis, ierr); axis.type = p->top_edge_type;
|
706
743
|
break;
|
707
|
-
default:
|
708
|
-
|
744
|
+
default:
|
745
|
+
RAISE_ERROR_i(
|
746
|
+
"Sorry: invalid 'loc' for edge: must be one of LEFT, RIGHT, TOP, or BOTTOM: is (%i)", location, ierr);
|
709
747
|
}
|
748
|
+
if (*ierr != 0) return;
|
710
749
|
axis.location = location;
|
711
|
-
c_show_side(fmkr, p, &axis);
|
712
|
-
done:
|
713
|
-
return fmkr;
|
750
|
+
c_show_side(fmkr, p, &axis, ierr);
|
714
751
|
}
|
715
752
|
|
716
753
|
|
717
|
-
|
754
|
+
void c_no_title(OBJ_PTR fmkr, FM *p, int *ierr)
|
718
755
|
{
|
719
|
-
FM *p = Get_FM(fmkr);
|
720
756
|
p->title_visible = false;
|
721
|
-
return fmkr;
|
722
757
|
}
|
723
758
|
|
724
|
-
|
759
|
+
void c_no_xlabel(OBJ_PTR fmkr, FM *p, int *ierr)
|
725
760
|
{
|
726
|
-
FM *p = Get_FM(fmkr);
|
727
761
|
p->xlabel_visible = false;
|
728
|
-
return fmkr;
|
729
762
|
}
|
730
763
|
|
731
|
-
|
732
|
-
VALUE FM_no_ylabel(VALUE fmkr)
|
764
|
+
void c_no_ylabel(OBJ_PTR fmkr, FM *p, int *ierr)
|
733
765
|
{
|
734
|
-
FM *p = Get_FM(fmkr);
|
735
766
|
p->ylabel_visible = false;
|
736
|
-
return fmkr;
|
737
767
|
}
|
738
768
|
|
739
|
-
|
740
|
-
VALUE FM_no_xaxis(VALUE fmkr)
|
769
|
+
void c_no_xaxis(OBJ_PTR fmkr, FM *p, int *ierr)
|
741
770
|
{
|
742
|
-
FM *p = Get_FM(fmkr);
|
743
771
|
p->xaxis_visible = false;
|
744
|
-
return fmkr;
|
745
772
|
}
|
746
773
|
|
747
|
-
|
748
|
-
VALUE FM_no_yaxis(VALUE fmkr)
|
774
|
+
void c_no_yaxis(OBJ_PTR fmkr, FM *p, int *ierr)
|
749
775
|
{
|
750
|
-
FM *p = Get_FM(fmkr);
|
751
776
|
p->yaxis_visible = false;
|
752
|
-
return fmkr;
|
753
777
|
}
|
754
778
|
|
755
|
-
|
756
|
-
VALUE FM_no_left_edge(VALUE fmkr)
|
779
|
+
void c_no_left_edge(OBJ_PTR fmkr, FM *p, int *ierr)
|
757
780
|
{
|
758
|
-
FM *p = Get_FM(fmkr);
|
759
781
|
p->left_edge_visible = false;
|
760
|
-
return fmkr;
|
761
782
|
}
|
762
783
|
|
763
|
-
|
764
|
-
VALUE FM_no_right_edge(VALUE fmkr)
|
784
|
+
void c_no_right_edge(OBJ_PTR fmkr, FM *p, int *ierr)
|
765
785
|
{
|
766
|
-
FM *p = Get_FM(fmkr);
|
767
786
|
p->right_edge_visible = false;
|
768
|
-
return fmkr;
|
769
787
|
}
|
770
788
|
|
771
|
-
|
772
|
-
VALUE FM_no_top_edge(VALUE fmkr)
|
789
|
+
void c_no_top_edge(OBJ_PTR fmkr, FM *p, int *ierr)
|
773
790
|
{
|
774
|
-
FM *p = Get_FM(fmkr);
|
775
791
|
p->top_edge_visible = false;
|
776
|
-
return fmkr;
|
777
792
|
}
|
778
793
|
|
779
|
-
|
794
|
+
void c_no_bottom_edge(OBJ_PTR fmkr, FM *p, int *ierr)
|
780
795
|
{
|
781
|
-
FM *p = Get_FM(fmkr);
|
782
796
|
p->bottom_edge_visible = false;
|
783
|
-
return fmkr;
|
784
797
|
}
|
785
798
|
|