diff options
-rwxr-xr-x | Master/texmf-dist/metapost/context/third/gnuplot/mp-gnuplot.mp | 904 | ||||
-rwxr-xr-x | Master/texmf-dist/tex/context/third/gnuplot/t-gnuplot.tex | 925 | ||||
-rwxr-xr-x | Master/tlpkg/bin/ctan2tds | 1 | ||||
-rwxr-xr-x | Master/tlpkg/bin/tlpkg-ctan-check | 1 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/collection-context.tlpsrc | 2 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/context-gnuplot.tlpsrc | 2 |
6 files changed, 1835 insertions, 0 deletions
diff --git a/Master/texmf-dist/metapost/context/third/gnuplot/mp-gnuplot.mp b/Master/texmf-dist/metapost/context/third/gnuplot/mp-gnuplot.mp new file mode 100755 index 00000000000..4b8e1c49256 --- /dev/null +++ b/Master/texmf-dist/metapost/context/third/gnuplot/mp-gnuplot.mp @@ -0,0 +1,904 @@ + +if known context_gnuplot : endinput; fi; + +boolean context_gnuplot ; context_gnuplot := true; + + string gnuplotversion; + + def gp_setup_before = + enddef; + + def gp_setup_after = + enddef; + + newinternal gp_align_center, gp_align_left, gp_align_right; + gp_align_center := 0; + gp_align_left := 1; + gp_align_right := 2; + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% + %% Colors & Dashes + %% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + boolean gp_use_color; gp_use_color := true; + boolean gp_use_dashed; gp_use_dashed := true; + + % default background color (should we set it somewhere?) + color gp_color_background; gp_color_background := white; + % default foreground color (also set in t-gnuplot.tex) + color gp_color_foreground; gp_color_foreground := black; + % current color + color gp_color_current; gp_color_current := gp_color_foreground; + + % colors corresponding to linetypes + % + % LT_AXIS (-1) + % LT_BLACK (-2) + % LT_NODRAW (-3) + % LT_BACKGROUND (-4) + % LT_UNDEFINED (-5) + + color gp_color_lt[]; + numeric gp_num_linetype; gp_num_linetype := 9; + gp_color_lt[-4] = gp_color_background; + gp_color_lt[-3] = gp_color_background; % TODO: nodraw!!! + gp_color_lt[-2] = gp_color_foreground; + % TODO: do we need this to be configurable? + gp_color_lt[-1] = gp_color_foreground; % coordinate axes + gp_color_lt[0] = red; + gp_color_lt[1] = green; + gp_color_lt[2] = blue; + gp_color_lt[3] = magenta; + gp_color_lt[4] = cyan; + gp_color_lt[5] = yellow; + gp_color_lt[6] = black; + gp_color_lt[7] = (1,.3,0); % orange; perhaps it's defined already + gp_color_lt[8] = .5white; + + % dashes corresponding to linetypes - copied from PostScript terminal + % perhaps check the other terminals as well!!! + + % scaling factor for dash lengths + gp_scale_dashlength := 1; + % TODO: set some sensible default scaling factor (compare with PostScript) + gp_dashlength := 1; + + % TODO: watch out linecaps and linejoins !!! (possibly rewrite) + % TODO: compare with PostScript lines and possibly fix, + % so that they will match + % + % TODO: write a macro to make these definitions slightly nicer + % + % linecap := butt; ??? + picture gp_dash_lt[]; + gp_dash_lt[-3] := dashpattern(off 1) scaled (gp_scale_dashlength*gp_dashlength); % TODO: test!!! + gp_dash_lt[-2] := dashpattern(on 1) scaled (gp_scale_dashlength*gp_dashlength); + % for axes + gp_dash_lt[-1] := dashpattern(on 2 off 1) scaled (gp_scale_dashlength*gp_dashlength); + gp_dash_lt[0] := dashpattern(on 1) scaled (gp_scale_dashlength*gp_dashlength); + gp_dash_lt[1] := dashpattern(on 4 off 2) scaled (gp_scale_dashlength*gp_dashlength); + gp_dash_lt[2] := dashpattern(on 2 off 3) scaled (gp_scale_dashlength*gp_dashlength); + gp_dash_lt[3] := dashpattern(on 1 off 1.5) scaled (gp_scale_dashlength*gp_dashlength); + gp_dash_lt[4] := dashpattern(on 6 off 2 on 1 off 2) scaled (gp_scale_dashlength*gp_dashlength); + gp_dash_lt[5] := dashpattern(on 3 off 3 on 1 off 3) scaled (gp_scale_dashlength*gp_dashlength); + gp_dash_lt[6] := dashpattern(on 2 off 2 on 2 off 6) scaled (gp_scale_dashlength*gp_dashlength); + gp_dash_lt[7] := dashpattern(on 1 off 2 on 6 off 2 on 1 off 2) scaled (gp_scale_dashlength*gp_dashlength); + gp_dash_lt[8] := dashpattern(on 2 off 2 on 2 off 2 on 2 off 2 on 2 off 4) scaled (gp_scale_dashlength*gp_dashlength); + + % returns the color for the given linetype modulo gp_num_linetype + vardef gp_color_linetype(expr linetype) = + (if linetype < -3: + gp_color_lt[-3] +% else: + elseif linetype >= gp_num_linetype: + gp_color_lt[(linetype mod gp_num_linetype)] +% gp_color_lt[1] + else: + gp_color_lt[linetype] + fi) + % TODO: chech if the number is defined + % TODO: check if gp_use_color +% if linetype = -2 : +% gp_color_lt[-2] +% elseif linetype = -1 : +% gp_color_lt[-1] +% elseif linetype = -1 : +% gp_color_lt[-3] +% else : +% % TODO: check if the number is defined +% % check, if the number is positive +% gp_color_lt[ (linetype mod gp_num_linetype) ] +% fi; + enddef; + + def gp_dash_linetype(expr linetype) = + (if linetype < -3: + gp_dash_lt[-3] + elseif linetype >= gp_num_linetype: + gp_dash_lt[(linetype mod gp_num_linetype)] + else: + gp_dash_lt[linetype] + fi) + % TODO: chech if the number is defined + % TODO: check if gp_use_color +% if linetype = -2 : +% gp_color_lt[-2] +% elseif linetype = -1 : +% gp_color_lt[-1] +% elseif linetype = -1 : +% gp_color_lt[-3] +% else : +% % TODO: check if the number is defined +% % check, if the number is positive +% gp_color_lt[ (linetype mod gp_num_linetype) ] +% fi; + enddef; + + % gp_set_color(lt(3)) + % gp_set_color(rgb(.5,.5.0)) + % gp_set_color(frac(.3)) + def gp_set_color(text t) = + begingroup; + % sets the color to the given (r,g,b) triple + def rgb(expr r,g,b) = + gp_color_current := (r,g,b); + enddef; + + % sets the color so that it matches the color of linetype + def lt(expr linetype) = + gp_color_current := gp_color_linetype(linetype); + enddef; + + % sets the color either to gray or according to the current palette + def frac(expr fraction) = + % "if palette = gray" + if gp_palette_color_mode = gp_palette_color_mode_rgb: + gp_color_current := ( + gp_palette_function(gp_palette_formula_r,fraction), + gp_palette_function(gp_palette_formula_g,fraction), + gp_palette_function(gp_palette_formula_b,fraction)); + else: + % TODO - more advanced paletter + gp_color_current := fraction*white; % XXX: should this be (1-frac)*white perhaps? + fi; + enddef; + + % execute the content - calls one of the definitions from above + t; + endgroup; + enddef; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% + %% Palette + %% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % for "colorMode==SMPAL_COLOR_MODE_GRADIENT" + % These variables are used to define interpolated color palettes: + % there are gradient_num pairs of (frac/gray, color) mappings +% numeric gp_palette.gradient_num; +% numeric gp_palette.gradient[].frac; +% color gp_palette.gradient[].abc; + % + % see palette_color_mode in color.h + newinternal + gp_palette_color_mode_none, + gp_palette_color_mode_gray, + gp_palette_color_mode_rgb, + gp_palette_color_mode_functions, + gp_palette_color_mode_gradient; + + gp_palette_color_mode_none := 0; + gp_palette_color_mode_gray := 1; % grayscale only + gp_palette_color_mode_rgb := 2; % one of several fixed transformations + gp_palette_color_mode_functions := 3; % user-defined transforms + gp_palette_color_mode_gradient := 4; % interpolated table: explicitely defined or read from file + + % there is no palette initialized by default + numeric gp_palette_color_mode; + gp_palette_color_mode := gp_palette_color_mode_none; + + % mapping formulae for gp_palette_color_mode_rgb + numeric gp_palette_formula_r; gp_palette_formula_r := 3; % f(x)=x + numeric gp_palette_formula_g; gp_palette_formula_g := 3; + numeric gp_palette_formula_b; gp_palette_formula_b := 3; + + % explicitely defined color gradient + color gp_palette_gradient_colors[]; + numeric gp_palette_gradient_pos[]; + % number of defined colors + numeric gp_palette_gradient_n; + + % gamma for gray scale palettes only + numeric gp_palette_gamma; + +% % color model: RGB/HSV/CMY; YIQ, XYZ and others not supported +% newinternal gp_palette.model.rgb, gp_palette.model.hsv, gp_palette.model.cmy;%, gp_palette.model.yiq, gp_palette.model.xyz; +% gp_palette.rgb := 0; +% gp_palette.hsv := 1; +% gp_palette.cmy := 2; + %gp_palette.yiq := 3; + %gp_palette.xyz := 4; + + % color model - RGB/HSV/CMY (ie. one of the models above) +% numeric gp_palette.model; + + % for "colorMode == SMPAL_COLOR_MODE_FUNCTIONS" + % R, G abd B for RGB + % H, S and V for HSV + % C, M and Y for CMY +% color gp_palette.abc; + + % gamma (only used for gray scale palettes) +% numeric gp_palette.gamma; gp_palette.gamma = 1; + + def gp_make_palette(text t) = + begingroup; + % let hack: save comma +% let@=,; + + def color_mode(text mode) = + % let hack +% let,=@; let@=,; + save gray, rgb, functions, gradient; + gray = gp_palette_color_mode_gray; + rgb = gp_palette_color_mode_rgb; + functions = gp_palette_color_mode_functions; + gradient = gp_palette_color_mode_gradient; + + gp_palette_color_mode := mode; + + % if mode=gray: + % % TODO + % elseif mode=rgb: + % % TODO + % elseif mode=functions: + % % TODO + % elseif mode=gradient: + % % TODO + % fi; + + % let hack: ignore next comma +% let,=;; + enddef; + + % for gp_palette_color_mode_rgb: numbers of formulae + def formulae(expr r, g, b) = + % let hack +% let,=@; let@=,; + gp_palette_color_mode := gp_palette_color_mode_rgb; + gp_palette_formula_r := r; + gp_palette_formula_g := g; + gp_palette_formula_b := b; + % let hack: ignore next comma +% let,=;; + enddef; + + % TODO: for gradient definitions + def colors(text tc) = + gp_palette_gradient_n := 0; + for i=tc: + gp_palette_gradient_colors[gp_palette_gradient_n] := i; + counter := counter+1; + endfor; + % let hack +% let,=@; let@=,; + % code goes here + % [TODO] + % + % let hack: ignore the following comma +% let,=;; + enddef; + + % TODO: for gradient definitions + def positions(text tp) = + gp_palette_gradient_n := 0; + for i=tp: + gp_palette_gradient_pos[gp_palette_gradient_n] := i; + counter := counter+1; + endfor; + % let hack +% let,=@; let@=,; + % code goes here + % [TODO] + % + % let hack: ignore the following comma +% let,=;; + enddef; + + t; + % let hack: restore comma +% let,=@; + endgroup; + enddef; + + % Functions copied from GetColorValueFromFormula from getcolor.c + vardef gp_palette_function(expr ff, tt) = + save f, t; + f = ff; + t = tt; + % the input gray is supposed to be in interval [0,1] + % for a negative formula, reverse the palette (negate x) + if f < 0: + t := -t; + f := -f; + fi; + + t := + if f = 0: 0 + elseif f = 1: 0.5 + elseif f = 2: 1 + elseif f = 3: t + elseif f = 4: t*t + elseif f = 5: t*t*t + elseif f = 6: t*t*t*t + elseif f = 7: sqrt(t) + elseif f = 8: sqrt(sqrt(t)) + elseif f = 9: sind(90t) + elseif f = 10: cosd(90t) + elseif f = 11: abs(t-0.5) + elseif f = 12: (2t-1)*(2t-1) + elseif f = 13: sind(180t) + elseif f = 14: abs(cosd(180t)) + elseif f = 15: sind(360t) + elseif f = 16: cosd(360t) + elseif f = 17: abs(sind(360t)) + elseif f = 18: abs(cosd(360t)) + elseif f = 19: abs(sind(720t)) + elseif f = 20: abs(cosd(720t)) + elseif f = 21: 3t + elseif f = 22: 3t-1 + elseif f = 23: 3t-2 + elseif f = 24: abs(3t-1) + elseif f = 25: abs(3t-2) + elseif f = 26: 1.5t-0.5 + elseif f = 27: 1.5t-1.0 + elseif f = 28: abs(1.5t-0.5) + elseif f = 29: abs(1.5t-1.0) + elseif f = 30: if t <= 0.25: 0 + elseif t <= 0.57: t/0.32-0.78125 + else : 1 + fi + elseif f = 31: if t <= 0.42: 0 + elseif t <= 0.92: 2t-0.84 + else : 1 + fi + elseif f = 32: if t <= 0.42: 4t + elseif t <= 0.92: -2t+1.84 + else : t/0.08-11.5 + fi + elseif f = 33: abs(2t-0.5) + elseif f = 34: 2t + elseif f = 35: 2t-0.5 + elseif f = 36: 2t-1.0 + else : t % ERROR + fi; + + if t < 0: 0 + elseif t < 1: t + else : 1 + fi + + % TODO: add a note to getcolor.c + enddef; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% + %% Scaling factors + %% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % scaling factor for points + gp_scale_pointsize := 1; + % scaling factor for line widths (for the whole plot) + gp_scale_linewidth := 1; + % current linewidth + gp_linewidth := 1; + % base linewidth: 0.4bp + gp_internal_linewidth := 0.4; + + numeric gp_linetype; gp_linetype := -3; + + % set the scaling factor for point sizes + def gp_set_pointsize(expr pointsize) = + gp_scale_pointsize := pointsize; + enddef; + % set the scaling factor for line widths + def gp_set_linewidth(expr linewidth) = + gp_linewidth := linewidth*gp_scale_linewidth*gp_internal_linewidth; + enddef; + % set the linetype: + % -3: solid with XOR, probably don't need that + % -2: border, perhaps always with linejoin mitered + % -1: axis + % 0 or more : the rest + def gp_set_linetype(expr linetype) = + gp_linetype := linetype; + gp_color_current := gp_color_linetype(linetype); + enddef; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% + %% FONTS & strings + %% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % support for textext("...") has been dropped for two reasons: + % - I don't intend to support it any more + % - Extremely inefficient anyway (almost useless for gnuplot-generated graphics) + + % scalig factor for text labels (relative to the document font) + % if you set the font to 10pt and use scaling factor 0.7, + % you'll get 7pt, not 10pt (but using the scaled 10pt design size ;) + numeric gp_scale_text; gp_scale_text := 1; + + % Returns the (image of) text: vertically centered and horizontally aligned + % according to the parameter align, which can be one of: + % - gp_align_center + % - gp_align_left + % - gp_align_right + % + % The code used to support string as input parameter (for textext("...")), + % but this only complicated the thing and is of no real use any more. + vardef gp_the_text(expr align, pict) = + save shift_x, shift_y; + + shift_y = -ypart center pict; + shift_x = -xpart + % horizontal alignment + if align = gp_align_center : center + elseif align = gp_align_left : llcorner + elseif align = gp_align_right : lrcorner fi + pict; + + (pict shifted (shift_x, shift_y)) + enddef; + + % % obsolete code to be removed + % + % % horizontal alignment + % if align = gp_align_center : + % pict := pict shifted (xpart(.5[llcorner pict,lrcorner pict]),0); + % elseif align = gp_align_left : + % pict := pict shifted (- xpart(llcorner pict),0); + % elseif align = gp_align_right : + % pict := pict shifted (- xpart(lrcorner pict),0); + % fi; + % % Hans wanted to persuade me to make the code shorter + % % (zero is replicated three times), but I prefer clarity against sparing + % % two bytes + % + % pict + + + % Places text on position "pos": + % - vertically centered + % - horizontal alignment is determined from optional arguments - centered by default + % - angle of rotation from optional parameters + % - magnification is determined from "gp_scale_text" + % + % syntax: + % gp_put_text((1cm,2cm),\sometxt[gp]{without optional parameters}) + % gp_put_text(origin, align_left, angle(15), \sometxt[gp]{with an arbitrary number of optional parameters}) + % + % The default alignment is centered, the default angle of rotation is zero. + % \sometxt{} or (theoretically) any picture argument should come last + def gp_put_text(expr pos)(text t) = + save arg_angle; arg_angle=0; + save arg_align; arg_align=gp_align_center; + + save pict; picture pict; + + begingroup; + + save left, right, center; + left = gp_align_left; + right = gp_align_right; + center = gp_align_center; + + % dirty trick: let makes the comma behave as semicolon, + % allowing comma-separated functions in "text t" + let@=,; + + def angle(expr a) = + let,=@; let@=,; + arg_angle := a; + let,=;; + enddef; + + % def align_left = + % let,=@; let@=,; + % arg_align := gp_align_left; + % let,=;; + % enddef; + % def align_right = + % let,=@; let@=,; + % arg_align := gp_align_right; + % let,=;; + % enddef; + % def align_center = + % let,=@; let@=,; + % arg_align := gp_align_center; + % let,=;; + % enddef; + + def align(expr a) = + let,=@; let@=,; + arg_align := a; + let,=;; + enddef; + + % converts the whole argument into a picture + % + % The problem is that \sometxt[gp]{text} is the very last command and cannot be captured as an image otherwise + % if you know a cleaner solution, please let me know + vardef dummy(text tt) = + tt + enddef; + pict := dummy(t); + + let,=@; + endgroup; + + draw (gp_the_text(arg_align, pict) scaled gp_scale_text rotated arg_angle shifted pos) withcolor gp_color_current; + enddef; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% + %% drawing and filling + %% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % low-level interface may change !!! + picture gp_pattern_image[], gp_pattern_current, gp_pattern_type[]; + numeric gp_num_patterns; gp_num_patterns := 11; + % TODO: redraw the patterns if necessary (if linewidth changes for example) + numeric gp_pattern_linewidth; gp_pattern_linewidth := .5gp_scale_linewidth*gp_internal_linewidth; + + numeric gp_pattern_name_empty; gp_pattern_name_empty := 0; + numeric gp_pattern_name_full ; gp_pattern_name_full := 3; + + % default patterns (PostScript-like) + % + % 0: empty + gp_pattern_image[0] := image( + setbounds currentpicture to unitsquare; + ); + % 3: full + gp_pattern_image[3] := image( + % fill unitsquare enlarged .1; + % setbounds currentpicture to unitsquare; + fill fullsquare xyscaled (5cm,5cm); +% fill fullsquare xyscaled (2.5w,2.5h); + ); + % 4: \ + gp_pattern_image[4] := image( % TODO!!! + draw ((1,-1)--(-1,1)) scaled 2mm withpen pencircle scaled gp_pattern_linewidth; + setbounds currentpicture to unitsquare scaled 2mm; + ); + % 5: / + gp_pattern_image[5] := image( % TODO!!! + draw ((-1,-1)--(1,1)) scaled 2mm withpen pencircle scaled gp_pattern_linewidth; + setbounds currentpicture to unitsquare scaled 2mm; + ); + % 6: \ + gp_pattern_image[6] := image( % TODO!!! + draw ((1,-2)--(-1,2)) scaled 2mm withpen pencircle scaled gp_pattern_linewidth; + setbounds currentpicture to unitsquare scaled 2mm; + ); + % 7: / + gp_pattern_image[7] := image( % TODO!!! + draw ((-1,-2)--(1,2)) scaled 2mm withpen pencircle scaled gp_pattern_linewidth; + setbounds currentpicture to unitsquare scaled 2mm; + ); + % 1: 4+5 + gp_pattern_image[1] := image( + draw gp_pattern_image[4]; + draw gp_pattern_image[5]; + ); + % 2: 4+5, bolj tesno skupaj + gp_pattern_image[2] := image( + draw gp_pattern_image[1]; + draw gp_pattern_image[1] shifted (.5bbwidth(gp_pattern_image[1]),0); + ); + + % argument: 2 times radius + vardef gp_pattern_image_circles(expr d) = image ( + draw fullcircle scaled d withpen pencircle scaled gp_pattern_linewidth; + setbounds currentpicture to fullsquare scaled d; + ) enddef; + + vardef gp_pattern_image_roof(expr d) = image ( + save p; path p; p = fullcircle cutbefore (point 4 of fullcircle); + draw p scaled d withpen pencircle scaled gp_pattern_linewidth; + draw p shifted (.5,.5) scaled d withpen pencircle scaled gp_pattern_linewidth; + setbounds currentpicture to unitsquare shifted (0,-.5) scaled d; + ) enddef; + + vardef gp_pattern_image_brick(expr width, height) = image ( +% save p; path p; p = unitsquare shifted (-.25,-.5) scaled; + draw unitsquare shifted (-.25,-.5) xyscaled (width,height) withpen pencircle scaled gp_pattern_linewidth; + draw unitsquare shifted ( .25, .5) xyscaled (width,height) withpen pencircle scaled gp_pattern_linewidth; + setbounds currentpicture to unitsquare yscaled 2 shifted (-.25,-.5) xyscaled (width,height); + ) enddef; + + for i=0 upto 7: + gp_pattern_type[i] := gp_pattern_image[i]; + endfor; + + gp_pattern_type[8] := gp_pattern_image_circles(2mm); + gp_pattern_type[9] := gp_pattern_image_roof(1.5mm); + gp_pattern_type[10] := gp_pattern_image_brick(2mm,1mm); + + % TODO: filling with a pattern: not implemented yet (implement approximately 8 patterns) + def gp_fill_pattern(expr p, pattern) = + save arg_pattern; arg_pattern = pattern mod gp_num_patterns; + + if pattern = gp_pattern_name_full: + % fill the area + fill p withcolor gp_color_current; + elseif pattern = gp_pattern_name_empty : + % nothing to do + else: + gp_pattern_current := gp_pattern_type[arg_pattern]; + % TODO: check if it exists! + + save maxi; maxi = max(10,bbwidth (p)/bbwidth (gp_pattern_current)+1); + save maxj; maxj = max(10,bbheight(p)/bbheight(gp_pattern_current)+1); + draw image ( + for i=-1 upto maxi: + for j=0 upto maxj: + draw gp_pattern_current shifted (i*bbwidth(gp_pattern_current),j*bbheight(gp_pattern_current)) shifted llcorner p withcolor gp_color_current; + endfor; + endfor; + clip currentpicture to p; + ); + fi; + enddef; + + % fill a closed path with current color with density "density" + % (0: background color, 1: current color) + % + % TODO (once in the future): fill with smooth shading & pattern fill + % + % p - path to be filled + % density - density of the color (between 0 and 1) + def gp_fill_density(expr p, density) = + fill (p) withcolor density[gp_color_background,gp_color_current]; + enddef; + def gp_fill_transparent(expr p, density) = + fill (p) withcolor transparent(1,density,gp_color_current); + enddef; + % filling (default: with density 1) + % optional parameters: + % transparent | (present or not, may be combined with both pattern and the solid fill) + % density(float between [0,1]) + % pattern(number of pattern) + % + % If pattern is called at least once, [transparent] pattern will be drawn, + % otherwise just a [transparent] solid area. + def gp_fill(text t) = + % mandatory parameter: path to be stroked + save arg_path; path arg_path; + save arg_pattern; + % default density is 100 % + save arg_density; arg_density := 1; + % for transparent density fills or transparent patterns + % (but transparent patterns are not implemented yet) + save arg_is_transparent; boolean arg_is_transparent; arg_is_transparent := false; + + % since we redefine "transparent", we need to restore the original macro again + % before calling gp_fill_transparent, which uses that one + begingroup; + save transparent, density, pattern; + + let@=,; + + % this function can be called for transparent (solid) fills or patterns + def transparent = + let,=@; let@=,; + arg_is_transparent := true; + let,=;; + enddef; + + def density(expr dens) = + let,=@; let@=,; + arg_density := dens; + let,=;; + enddef; + + def pattern(expr pat) = + let,=@; let@=,; + arg_pattern := pat; + let,=;; + enddef; + + % execute the content ("read function arguments") + let,=;; + % this will read the first mandatory argument (path) into arg_p and execute any subsequent functions + arg_path := t; + let,=@; + endgroup; + + % pattern fill + if known arg_pattern: + gp_fill_pattern(p, arg_pattern); + % transparent solid fill + elseif arg_is_transparent: + gp_fill_transparent(p, arg_density); + % non-transparent solid fill + else: + gp_fill_density(p,arg_density); + fi; + enddef; + + def gp_draw(expr p) = + draw (p) withcolor gp_color_current withpen pencircle scaled gp_linewidth + % axes should be drawn with only one half of the default linewidth + % TODO: do we need this to be configurable? + if gp_linetype = -1: scaled .5 fi + if gp_use_dashed: dashed gp_dash_linetype(gp_linetype) + % TODO: make this definition nicer (combine with the definition above) + elseif gp_linetype = -1: dashed gp_dash_linetype(gp_linetype) fi; + enddef; + + def gp_dot(expr x,y) = + drawdot shifted (x,y) withcolor gp_color_current withpen pencircle scaled gp_linewidth; + enddef; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% + %% Poins & Symbols + %% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % should we draw the points using metapost or typeset them using TeX? + newinternal gp_points_with_metapost, gp_points_with_tex; + gp_points_with_metapost := 0; + gp_points_with_tex := 1; + + numeric gp_points_with; + % default is to draw the points with metapost rather than typeset them + % with TeX + gp_points_with := gp_points_with_metapost; + + % the number of point types + numeric gp_num_points_with_tex, gp_num_points_with_metapost; + + % returns a path representing a closed n-polygon, starting at upper corner (12 o'clock) + vardef fullpolygon(expr n) = + (for i=1 upto n: (up rotated ((i-1)*360/n)) -- endfor cycle) + enddef; + + %-------------------------% + % point shape definitions % + %-------------------------% + path gp_point_shape[]; + + % 0 - plus + gp_point_shape[0] := (0,0)--(-1,0)--(1,0)--(0,0)--(0,1)--(0,-1)--cycle; + % 1 - X + gp_point_shape[1] := (0,0)--(-1,-1)--(1,1)--(0,0)--(-1,1)--(1,-1)--cycle; + % 2 - star (+ & x) + gp_point_shape[2] := + (0,0)--(-1, 0)--(1, 0)-- + (0,0)--(-1,-1)--(1, 1)-- + (0,0)--(-1, 1)--(1,-1)-- + (0,0)--( 0,-1)--(0, 1)--cycle; + % 3, 4 - box + gp_point_shape[3] := (-1,-1)--(1,-1)--(1,1)--(-1,1)--cycle; + gp_point_shape[4] := gp_point_shape[3]; + % 5, 6 - circle + gp_point_shape[5] := fullcircle scaled 1.5; + gp_point_shape[6] := gp_point_shape[5]; + % 7, 8 - triangle + % scaled is such a way that it's exactly 2 units wide + gp_point_shape[7] := fullpolygon(3) scaled (1/cosd(30)); + gp_point_shape[8] := gp_point_shape[7]; + % 9, 10 - upside down triangle + gp_point_shape[9] := gp_point_shape[8] scaled -1; + gp_point_shape[10] := gp_point_shape[9]; + % 11, 12 - diamond + gp_point_shape[11] := (-1,0)--(0,-1)--(1,0)--(0,1)--cycle; + gp_point_shape[12] := gp_point_shape[11]; + % 13, 14 - pentagon + gp_point_shape[13] := fullpolygon(5) scaled (1/cosd(18)); + gp_point_shape[14] := gp_point_shape[13]; + + picture gp_point_pt[]; + + for i=0,1,2,3,5,7,9,11,13: + gp_point_pt[i] := image(draw gp_point_shape[i] scaled 3pt;); % TODO: fix the scale & linewidth + endfor; + for i=4,6,8,10,12,14: + gp_point_pt[i] := image(filldraw gp_point_shape[i] scaled 3pt;); % TODO: fix the scale & linewidth + endfor; + + % we have defined 15 point types so far + gp_num_points_with_metapost := 15; + + %-------------------------% + + % n is the number of symbol, but might a be a figure as well + vardef gp_the_symbol(expr n) = + picture pict; + % using metapost + if numeric n : + if n = -1 : + % point type -1 is always a dot + pict := image( fill fullcircle scaled 2gp_linewidth; ); + else : + if gp_points_with = gp_points_with_metapost : + % TODO + pict := gp_point_pt[(n mod gp_num_points_with_metapost)]; + else : + pict := sometxt((n mod gp_num_points_with_tex) + 1 + 500); + % XXX: 500 is a hack (see m/t-gnuplot.tex) and might need a fix + fi; + fi; + elseif picture n: + pict := n; + else: + pict := nullpicture; + fi + pict shifted -center pict + enddef ; + % the points have to be scaled slightly more + def gp_point(expr x, y, n) = + draw (gp_the_symbol(n) scaled (gp_scale_pointsize) shifted (x,y)) withcolor gp_color_current; + enddef ; + + endinput + +end. + + +% How to trick metapost to use comma between macros +% +%beginfig(1); +% +%def do_something(expr xx, yy)(text t) = +% save c; color c; c = black; +% save d; numeric d; d = 5pt; +% +% let@=,; +% +% def set_color(expr col) = +% let,=@; +% let@=,; +% c := col; +% let,=;; +% enddef; +% +% def set_size(expr size) = +% let,=@; +% let@=,; +% d := size; +% let,=;; +% enddef; +% +% t; +% let,=@; +% +% fill fullcircle scaled d shifted (xx,yy) withcolor c; +%enddef; +% +%do_something(1cm,2cm,set_color(blue)); +%do_something(2cm,1cm,set_size(10pt)); +%% this works OK +%%do_something(2.5cm,1.5cm,set_color(red) set_size(8pt)); +% +%% this works OK +%%do_something(2cm,2.5cm,set_color(green);set_size(8pt)); +% +%% but the following syntax looks better +%do_something(2.5cm,1.5cm,set_color(blue),set_size(8pt),set_color(red),set_size(2pt)); +% +%draw unitsquare scaled 3cm; +% +%endfig; +%end. diff --git a/Master/texmf-dist/tex/context/third/gnuplot/t-gnuplot.tex b/Master/texmf-dist/tex/context/third/gnuplot/t-gnuplot.tex new file mode 100755 index 00000000000..aff8d0fc2ff --- /dev/null +++ b/Master/texmf-dist/tex/context/third/gnuplot/t-gnuplot.tex @@ -0,0 +1,925 @@ +%D \module +%D [ file=t-gnuplot, +%D version=2007.02.07, +%D title=\CONTEXT\ Extra Modules, +%D subtitle=\GNUPLOT\ Inclusion, +%D author={Hans Hagen, Taco Hoekwater, Mojca Miklavec, (Aditya Mahajan)}, +%D date=\currentdate, +%D copyright=\PRAGMA] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This module is used for creating gnuplot graphs on-the-fly and including them +%D into documents. +%D +%D Known Bugs: +%D +%D \startitemize +%D \item spurious space \& page +%D \stopitemize +%D +%D TODO (Optimisations): +%D +%D \startitemize +%D \item optimize the number of gnuplot runs (if possible, gnuplot should be run only once) +%D \item optimize the number of times for loading/converting an already used graphic +%D \item pstopdf is a bit slow +%D \stopitemize +%D +%D TODO (Handle things that may go wrong): +%D - gnuplot executable doesn't exist +%D - context terminal isn't available or some other failure in gnuplot script (no file created) +%D - write18 disabled (you may call gnuplot later - create a script) +%D +%D TODO (Missing functionality): +%D +%D - a lot ... + +\writestatus{loading}{Gnuplot module} + +\startmodule[gnuplot] + +\unprotect + +\def\c!terminal {terminal} +\def\c!options {options} +\def\c!pointset {pointset} + +%D MPextensions +%D +%D XXX +%D if possible, they should be specific to \type{\startGNUPLOTgraphic}, +%D so unvisible to \type{MPcode} +%D (probably something like \type+\appendtoks ... to\everyGNUPLOTgraphic+) +\startMPextensions + % load metapost macros (only once) + input mp-gnuplot.mp ; + % number of points defined with \setupGNUPLOTterminal[pointset=...] + %gp_num_points_with_tex := \gp:num:pointswithtex; + gp_num_points_with_tex := 3; + % main color should be set equal to the current text color + gp_color_foreground := \MPcolor{currentcolor}; + gp_color_lt[-2] := gp_color_foreground; + % TODO: is there any chance to make this local to gnuplot? + % linejoin & linecap + linejoin := \@@GNUPLOT@term@context@linejoin; +% linecap := \gp:term:context:linecap; + % dashes or solid? (true/false) + gp_use_dashed := \@@GNUPLOT@term@context@is@dashed; + % dashlength scale +% gp_scale_dashlength := \gp:term:context:dashlength; + % linewidth scale + gp_scale_linewidth := \@@GNUPLOT@term@context@linewidth; + + gp_scale_text := \@@GNUPLOT@term@context@textscale; + + % linejoin := \gp:term:context:linejoin; + % linecap := \gp:term:context:linecap; + % % dashes or solid? (true/false) + % gp_use_dashed := \gp:term:context:dashed; + % % dashlength scale + % gp_scale_dashlength := \gp:term:context:dashlength; + % % linewidth scale + % gp_scale_linewidth := \gp:term:context:linewidth; + +\stopMPextensions + +%D (hopefully) temporary solution for handling the color in expressions like +%D \type+draw \sometxt{...} withcolor red+ +\chardef\TeXtextcolormode\zerocount + +%D We have to make sure that runtime MP graphics are enabled, +%D otherwise sizes of labels created by \type+\sometxt{}+ would be wrong +%D if user didn't enable that option in \type{cont-usr.tex}. +%D (Taco says it might be a bug, but let's not worry too much about it. +%D If it will be resolved, we may delete this.) +\runMPgraphicstrue + +%D We need a \type{\strut} in front of labels for better vertical centering. +%D This might still fail for Zapfino and alike where \type{\strut} might be smaller +%D than the actual font height. +%D +%D TODO (optional improvement): instead of placing \type{\strut} in front, +%D create a \type{\hbox} and adjust it's dimensions to \type{\strut}'s height and depth. + +%D Aditya, thanks a lot for requesting it! +%D Hans, thanks a lot for implementing this! +\definetextext[gp]{\strut} +%D TODO (feature request): +%D \starttyping +%D \sometxt[gp][ss,20pt]{abc} +%D \stoptyping +%D should become equivalent to +%D \starttyping +%D \sometxt{\switchtobodyfont[ss,20pt]\strut abc} +%D \stoptyping +%D +%D Or, even more drastic perhaps, I would love to implement +%D \starttyping +%D \sometxt[gp][iwona,bold,c]{abc} +%D \stoptyping +%D meaning: iwona, bold typeface, size \quote{c} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%D The following patch has been written by Aditya and seems to work OK, +%D however it would be more clean to have this functionality in the core. +%D Redefining low-level macros might be a bit dangerous, esp. since +%D they tend to change over time. +%D +%D TODO: remind Hans to implement it in core ;) +%D and remove this patch from the module + +\long\def\redofiltersometxt[#1]% +{\doifnextcharelse[{\reredofiltersometxt[#1]}{\redodofiltersometxt[#1]}} + +\long\def\redodofiltersometxt[#1]#2% + {\increment\txtcounter + \TeXtext[#1]\txtcounter{#2}% + \filtersometxt} + +\long\def\reredofiltersometxt[#1][#2]#3% + {\increment\txtcounter + \TeXtext[#1]\txtcounter{\switchtobodyfont[#2]\strut#3}% + \filtersometxt} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%D For the old method of \type{put_text("some text")} using textext: +%D not used/supported any more, but still here for testing purposes +%D (to be removed in the future) +\forceMPTEXcheck{put_text} +%\runMPTEXgraphicstrue + +\newcounter\GNUPLOTnumber + +%D \macros +%D {startGNUPLOTinclusions, resetGNUPLOTinclusions} +%D +%D For those who want to have two or more graphs with similar options, +%D these options may be included inside \type{\startMPinclusions ... \stopMPinclusions} +%D and will be place on the top of the created \GNUPLOT\ script. +%D +%D \starttyping +%D \startMPinclusions +%D set xlabel '$x$' +%D set ylabel '$y$' +%D set format y "%.1f" +%D \stopMPinclusions +%D +%D \startGNUPLOTscript{sin} +%D plot sin(x) +%D \stopGNUPLOTscript +%D \startGNUPLOTscript{cos} +%D plot cos(x) +%D \stopGNUPLOTscript +%D \stoptyping + +%D The code is not 100\% robust. Different characters and/or expansions may cause problems. +%D \type{\%} takes care for not ignoring what comes after \type{%}. +%D That might be only start of the game. +\long\def\startGNUPLOTinclusions + {\bgroup + \obeylines + \catcode`\%=\@@letter + \catcode`\|=\@@letter + \dostartGNUPLOTinclusions} + +\long\def\dostartGNUPLOTinclusions#1\stopGNUPLOTinclusions + {\gdef\GNUPLOTinclusions{#1}% + \egroup} + +\def\resetGNUPLOTinclusions{\let\GNUPLOTinclusions\empty} + +\resetGNUPLOTinclusions + +%D On the other hand, one can probably achieve the same effect +%D when drawing two plots inside the same script, like that: +%D +%D \starttyping +%D \startGNUPLOTscript{sin and cos} +%D set xlabel '$x$' +%D set ylabel '$y$' +%D set format y "%.1f" +%D plot sin(x) +%D plot cos(x) +%D \stopGNUPLOTscript +%D \stoptyping +%D +%D and then recall the graphics using \type{\useGNUPLOTgraphic[sin and cos][1]}. + +%D \macros +%D {startGNUPLOTscript} +%D +%D \starttyping +%D \startGNUPLOTscript{some name} +%D plot sin(x) +%D \stopGNUPLOTscript +%D \stoptyping + +%\long\def\startGNUPLOTscript#1% +% {\bgroup +% \obeylines +% \catcode`\%=\@@letter +% \dostartGNUPLOTscript{#1}} + +\def\startGNUPLOTscript + {\bgroup\dosingleempty\dostartGNUPLOTscript} + +\def\redostartGNUPLOTscript#1 + {\obeylines + \catcode`\%=\@@letter + \catcode`\|=\@@letter + \catcode`\$=\@@letter + \dodostartGNUPLOTscript{#1}% +%\dostartGNUPLOTscript[#2] +} + +\def\dostartGNUPLOTscript[#1]% + {\iffirstargument + \obeylines + \catcode`\%=\@@letter + \catcode`\|=\@@letter + \catcode`\$=\@@letter + \dodostartGNUPLOTscript{#1}% + \else + \redostartGNUPLOTscript + \fi +} + +% FIXME: +% Math labels still don't work properly +% plot x t '$\frac{2}{\sqrt{\pi}}e^{-x^2}$' +% will fail for example. +% +% Taco suggested to put \detokenize in front of the argument, +% but then I run into problems with newlines. +% I've lost too many nerves with ^^M already. +% This item should be somewhere on top of priority list, +% but I'm no TeXacker. +% +\long\def\dodostartGNUPLOTscript#1#2\stopGNUPLOTscript + {\doglobal\increment\GNUPLOTnumber + \letgvalue{gps:n:#1}\GNUPLOTnumber + \setgvalue{gps:d:\GNUPLOTnumber}{#2}% +% \setgvalue{gps:d:\GNUPLOTnumber}{\detokenize{#2}}% + \egroup} + +\long\def\dodostartGNUPLOTscript#1#2\stopGNUPLOTscript + {\doglobal\increment\GNUPLOTnumber + \letgvalue{gps:n:#1}\GNUPLOTnumber + \setgvalue{gps:d:\GNUPLOTnumber}{#2}% +% \setgvalue{gps:d:\GNUPLOTnumber}{\detokenize{#2}}% + \egroup} + + +\newtoks\everyGNUPLOTscript + +%D We need to preserve newline characters (\TeX\ doesn't distinguish them from spaces). +%D Finding the proper solution has costed quite some nerves: most solutions resulted in \type{^M}. + +\appendtoks + \obeylines + \def\obeyedline{\outputnewlinechar}% +\to \everyGNUPLOTscript + +%D Content of GNUPLOTscript has to be handled literally: +%D backslash (\letterbackslash) and percent (\%) may not interfere with \TeX. + +\appendtoks + \let\%\letterpercent + \def\ {\letterbackslash\outputnewlinechar}% + \catcode`\$=\@@letter +\to \everyGNUPLOTscript + +% When are the graphics processed/read? +% +% - \gps:n:{name} (gnuplot script:name:{name}) holds the number of gnuplot script; +% - that number was defined if we created the plot using \startGNUPLOTscript{name} +% - and most probably undefined if we only issued \processGNUPLOTfile[name][filename] +% => if, at the time of issuing \processGNUPLOTfile[name][filename], \gps:n:{name} is not defined, +% it should be defined at that time +% - \gpe:{name}:{terminal} (gnuplot graphic executed:{name}:{terminal}) +% is defined if we executed the command for that specific name and for that terminal +% (once it will probably be 0 for a failed run and 1 for a successful one) + +% \useGNUPLOTgraphic[name] has three different ways of working: +% - it can be called after \processGNUPLOTfile[name][filename] +% which defined MP graphics that are now used +% - it can be called for the first time under the current terminal +% in that case it compiles the graphic and includes it +% - it can be called for the second, third, ... time +% in which case it only includes files without compiling it + +%D \macros +%D {useGNUPLOTgraphic} + +% 5 ways of calling it: +% - \useGNUPLOTgraphic{name} +% - \useGNUPLOTgraphic[name] +% - \useGNUPLOTgraphic[name][1,2,5] +% - \useGNUPLOTgraphic[name][width=.8\textwidth] +% - \useGNUPLOTgraphic[name][1,2,5][width=.8\textwidth] + +% this code takes care of reading arguments +\def\useGNUPLOTgraphic + {\dotripleempty\douseGNUPLOTgraphic} + +\def\douseGNUPLOTgraphic[#1][#2][#3]% + {\doifelse{#3}{}{% + % < 3 arguments + \doifelse{#2}{}% + % 1 argument + % as in \useGNUPLOTgraphic[name] + {\dodouseGNUPLOTgraphic[#1][][]}% + % % as in \useGNUPLOTgraphic{name} + % {\redouseGNUPLOTgraphic[][][]}% + % 2 arguments + {\doifassignmentelse{#2}% + % as in \useGNUPLOTgraphic[name][width=.8\textwidth] + {\dodouseGNUPLOTgraphic[#1][][#2]}% + % as in \useGNUPLOTgraphic[name][1,2,5] + {\dodouseGNUPLOTgraphic[#1][#2][]}% + }% + }% + % as in \useGNUPLOTgraphic[name][1,2,5][width=.8\textwidth] + {\dodouseGNUPLOTgraphic[#1][#2][#3]}% + } + +\def\redouseGNUPLOTgraphic[#1][#2][#3]#4% + {\dodouseGNUPLOTgraphic[#4][][]} + +% and this code actually does something with it + +%D \doifundefined {string} {...} +%D \doifdefined {string} {...} +%D \doifundefinedelse {string} {then ...} {else ...} +%D \doifdefinedelse {string} {then ...} {else ...} + +% \doifGNUPLOTscriptdefined{name}{...} + +% if gnuplot script with {name} and current terminal has already been processed +% \doifGNUPLOTscriptprocessed{name}{...} + +% \letGNUPLOTscriptprocessed[optional terminal]{name} signals that the gnuplot script named {name} +% has already been processed with the current terminal +% TODO: currently it is always defined to be one as soon as one tries to process it, +% even if en error is produced; in future it would be helpful if it would be set to zero +% if it was unsuccessfully executed; +% that is needed, since scripts are processed only when one first asks for including the graphic +\def\letGNUPLOTscriptprocessed + {\dosingleempty\doletGNUPLOTscriptprocessed} +%\def\doletGNUPLOTscriptprocessed[#1]#2% +%{\letgvalue{gpe:#1:\@@GNUPLOTterminal}\plusone} +\def\doletGNUPLOTscriptprocessed[#1]#2% + {\iffirstargument + % terminal has been specified + \letgvalue{gpe:#2:#1}\plusone + \else + % no terminal specified - use the current one + \letgvalue{gpe:#2:\@@GNUPLOTterminal}\plusone + \fi} + +% Although that should preferably not happen, one might come to an idea of defining +% a gnuplot script with the same name as already defined. +% In that case the old script cannot be referenced any more, but we can still try +% to do out best to make it work anyway. We have to do two things: +% - claim that script with that name hasn't been defined yet, so that processing will happen again +% (TODO: do it in a more elegant way for all known terminals) +% - undefine any metapost graphics (TODO: I have no idea yet how it can be done) +% +% \resetGNUPLOTscriptprocessed{name} +\def\resetGNUPLOTscriptprocessed#1% + {\bgroup + % claim that the script with {name} (#1) hasn't been processed with {terminal} (##1) yet + \def\undefineGNUPLOTscriptforterminal##1{\letbeundefined{gpe:#1:##1}}% + % TODO: the list of available terminals should be generated automatically + \processcommalist[context,postscript,ps,eps,pdf,metapost,mp,png]\undefineGNUPLOTscriptforterminal + \resetGNUPLOTgraphics{#1}% + \egroup} + +% \resetGNUPLOTgraphics{name} undefines any gnuplot graphic defined with \startGNUPLOTgraphic[name][number] +\def\resetGNUPLOTgraphics#1% + {\doloop + {\doifMPgraphicelse{gpg:#1:\recurselevel}% + % TODO: be aware - @@MPG is low-level ConTeXt variable which might change without notice, + % it would be better to call this \undefineMPgraphic{gpg:#1:\recurselevel} or something similar + {\letbeundefined{@@MPGgpg:#1:\recurselevel}}% + {\exitloop}}% + }% + +% TODO: this can probably be done in a better way +\def\doifGNUPLOTscriptprocessed#1#2% + {\doifdefined {gpe:#1:\@@GNUPLOTterminal}{#2}} +\def\doifGNUPLOTscriptprocessedelse#1#2#3% + {\doifdefinedelse {gpe:#1:\@@GNUPLOTterminal}{#2}{#3}} +\def\doifGNUPLOTscriptnotprocessed#1#2% + {\doifundefined {gpe:#1:\@@GNUPLOTterminal}{#2}} +\def\doifGNUPLOTscriptnotprocessedelse#1#2#3% + {\doifundefinedelse{gpe:#1:\@@GNUPLOTterminal}{#2}{#3}} + + +% private +% \writeandprocessGNUPLOTscript{name} +\def\writeandprocessGNUPLOTscript#1% + % TODO: if gps:n:#1 (holding the script content) is not defined, + % error or warning should be issued + % + % only process the script if it has been defined and not processed before for the current terminal + {\doifdefined{gps:n:#1}{\doifGNUPLOTscriptnotprocessed{#1}{% + % \gpe:{name}:{terminal} is defined + %\setgvalue{gpe:#1:\@@GNUPLOTterminal}{#2} + \letGNUPLOTscriptprocessed{#1} + % call to gnuplot and processing/converting the graphics is only needed in the first ConTeXt run + \doifmode{*\v!first}{% (perhaps also: if files haven't changed) + \bgroup + % catcodes trickery & alike + \the\everyGNUPLOTscript + % open file for writing + \immediate\openout\scratchwrite=\GNUPLOTfile.plt + % TODO: terminal-specific options (default or provided by the user) + \immediate\write\scratchwrite{\letterhash\space Do not modify this file - all changes will be overwritten}% + \immediate\write\scratchwrite{\letterhash\space Change \jobname.tex instead.}% + \immediate\write\scratchwrite{set terminal \@@GNUPLOToutput\space\@@GNUPLOToptions}% + % add common inclusions in scripts for multiple similar plots + \doifnotempty + {\GNUPLOTinclusions}{\immediate\write\scratchwrite{\GNUPLOTinclusions}}% + \immediate\write\scratchwrite{set output "\@@GNUPLOTresult"}% + % write main contents of the script, like "plot sin(x)" + \immediate\write\scratchwrite{\getvalue{gps:d:\GNUPLOTnumber}}% + \immediate\closeout\scratchwrite + \egroup + % TODO: + % - check the state of write18 and warn the user if it's disabled, + % otherwise just everyone will start complaining that the module doens't work + % - check if execution was successful; possible pitfalls: + % - gnuplot doesn't exist as a binary + % - gnuplot doesn't support context terminal + % or some other error in script which results in empty output file + % + % run gnuplot & execute the script that has just been written + \executesystemcommand{texmfstart --ifchanged=\GNUPLOTfile.plt\space + --direct \@@GNUPLOTprogram\space\GNUPLOTfile.plt}% + \convertGNUPLOTgraphic + }% + % for ConTeXt terminal only - read the result + \doif{\@@GNUPLOTterminal}{context}{\processGNUPLOTfile[#1][\@@GNUPLOTresult]}% + }}} + +% \dodouseGNUPLOTgraphic[name][numbers][options] +\def\dodouseGNUPLOTgraphic[#1][#2][#3]% + {\bgroup + \doifdefined{gps:n:#1} + {\edef\GNUPLOTnumber{\getvalue{gps:n:#1}}% + \edef\GNUPLOTfile {\bufferprefix gnuplot-\GNUPLOTnumber}% + \writeandprocessGNUPLOTscript{#1}% + % "ctxtools --purge" should delete the gnuplot script and other intermediate files + % (but it seems that they are deleted automatically already; preferred or not?) +% \registertempfile{\GNUPLOTfile.plt} +% \registertempfile{\@@GNUPLOTresult} +% \registertempfile{\@@GNUPLOTfinalresult} + \doifelse{\@@GNUPLOTterminal}{context}% + % for ConTeXt terminal only + {\doifelse{#2}{}% + % if no explicit figure number was specified, include all the figures + {\doloop + {\doifMPgraphicelse{gpg:#1:\recurselevel}% + {\scale[#3]{\reuseMPgraphic{gpg:#1:\recurselevel}}}% + {\exitloop}}}% + % if numbers were specified, include the figures specified in the list only + {\begingroup + \def\useGNUPLOTgraphicN##1{\doifMPgraphicelse + {gpg:#1:##1}% + {\scale[#3]{\reuseMPgraphic{gpg:#1:##1}}}% + % if graphic doesn't exist: draw a dummy frame instead and warn the user + {\scale[#3]{\framed[frame=on,width=5in,height=3in,align={middle,lohi}]{GNUPLOT graphic #1, Nr. ##1 doesn't exist}}}}% + \processcommalist[#2]\useGNUPLOTgraphicN + \endgroup + }% + }% + % for all the other terminals + % TODO: add more safety switches (if pages don't exist for example) + {\doifelse{#2}{}% + % if no explicite figure number was specified, include all the pages + % TODO: properly handle METAPOST & PNG (only works for (E)PS & PDF) !!! + {\getfiguredimensions[\@@GNUPLOTresult]% + \dorecurse{\noffigurepages}{\externalfigure[\@@GNUPLOTfinalresult][page=\recurselevel,#3]}}% + % if numbers were specified, include the pages specified in the list only + {\begingroup + \def\useGNUPLOTgraphicN##1{\externalfigure[\@@GNUPLOTfinalresult][page=##1,#3]}% + \processcommalist[#2]\useGNUPLOTgraphicN + \endgroup + }% + }% + }% + \egroup} + +%D \macros +%D {setupGNUPLOT} + +\def\setupGNUPLOT +% {\dodoubleempty\getparameters[@@GNUPLOT]} + {\dosingleargument\dosetupGNUPLOT} + +\def\dosetupGNUPLOT[#1]% + {\getparameters[@@GNUPLOT][#1]% + % define all the necessary points according to the option "pointset" + % + % XXX: no idea why this is needed, but otherwise it complains that @@GNUPLOTpointset is undefined + \edef\currentGNUPLOTpointset{\@@GNUPLOTpointset}% + \startTeXtexts + \doloop{\doifelseconversionnumber{\@@GNUPLOTpointset}{\recurselevel}% + % +500 is a hack (hopefully the plot doesn't contain more than 500 labels) + % otherwise the points would be overwritten by labels with another \TeXtext: + % it might need a fix in ConTeXt core + {\TeXtext{\numexpr\recurselevel+500\relax}{{\convertnumber{\currentGNUPLOTpointset}{\recurselevel}}}}% + {\exitloop}}% + \stopTeXtexts + % \gp:num:pointswithtex is passed to metapost, so that it knows + % how many points are defined and chooses the proper point + % form a set of the defined ones + % + % for safety reasons define \gp:num:pointswithtex to be equal to 1 (it can only increase later), otherwise: + % - (something mod 0) won't work + % - if conversion is not defined, the number will retain its old value (not desirable) + \edef\gp:num:pointswithtex{1}% + \doloop{\doifelseconversionnumber{\@@GNUPLOTpointset}{\recurselevel}% + {\edef\gp:num:pointswithtex{\recurselevel}}% + {\exitloop}}% + % TODO: + % - issue a warning if user wants to use points with TeX, + % but pointset= is undefined (if the first point doesn't exist) + % - no idea what happens if conversion is infinite, + % so try to stop at some reasonable value (100?) + % - current implementation redefines the points even if only terminal type + % has been set to some other value (which is a stupid approach, but I + % wanted to have a working version first and will consider efficiency later) + % - it may be that the old points remain defined if conversion changes + % (perhaps they should be undefined again?) + } + +% Hans has written this piece of code, but: +% - "start" and "/MIN" caused problems +% - pgnuplot is not much more "portable" than gnuplot +% best thing to do is to create a "gnuplot.bat" somewhere in PATH +% +%\def\processGNUPLOTscript +% {\doifelse\operatingsystem{mswin} +% {\executesystemcommand{start /MIN pgnuplot \GNUPLOTfile.plt}} % start is needed else gp fails +% {\executesystemcommand{gnuplot \GNUPLOTfile.plt}}} +%\def\processGNUPLOTscript +% {\executesystemcommand{gnuplot \GNUPLOTfile.plt}} + +% TODO: check if write18 is enabled; if not, issue a command and warn the user that running the module might be pointless or that he/she has to run gnuplot on the produced files manually +\def\convertGNUPLOTgraphic + {\doifsomething\@@GNUPLOThandle{\executesystemcommand{\@@GNUPLOThandle}}} + +%D \macros +%D {processGNUPLOTfile} + +%D It's needed to input a file resulting from a gnuplot run (with ConTeXt terminal). +%D It reads the file and "saves" the metapost graphics defined in that file, +%D so that they can be used with \usegnuplotgraphic (low level: \reuseMPgraphic) later +%D +% \processGNUPLOTfile[NAME][filename] +\def\processGNUPLOTfile + {\dodoubleargument\doprocessGNUPLOTfile} + +\def\doprocessGNUPLOTfile[#1][#2]% + {% we first define two commands: \startGNUPLOTgraphic & \stopGNUPLOTgraphic to read the files in; + % files that gnuplot creates in non-standalone mode look approximately like this: + % + % \startGNUPLOTgraphic[1] + % ... metapost commands to draw the graph ... + % \stopGNUPLOTgraphic + % \startGNUPLOTgraphic[2] + % ... metapost commands to draw the graph ... + % \stopGNUPLOTgraphic + % ... + % + % while reading the file in, metapost graphics named "gpg:{name}:{number}" are defined + % + % (we might need some additional arguments later on, but for now the figure number should suffice) + \def\startGNUPLOTgraphic + {\obeyMPlines % <- no longer a problem + \def\obeyedline{}% <- thanks to this + \dosingleargument\dostartGNUPLOTgraphic}% + \long\def\dostartGNUPLOTgraphic[##1]##2\stopGNUPLOTgraphic + {\startreusableMPgraphic{gpg:#1:##1}##2\stopreusableMPgraphic}% + % + % if gps:n:{name} (which is a number) is not defined, + % then we first have to increase the \GNUPLOTnumber counter and associate this name with the new number + + % , then we should now also define + % gpe:{number}:context which should signal later on that the graphic +% \doifdefined{gps:n:#1} + % input the file + % TODO: error / warning if the files doesn't exist + \readlocfile{#2}{}{}% the third argument should be: if file not found + % this file is known + % TODO \letgvalue{gpf:#1}\plusone + } + +%D \macros +%D {startGNUPLOTpage} +%D +%D Used for standalone \GNUPLOT\ figures & written out by gnuplot in standalone mode. +%D +%D Instead of having to \type{\useGNUPLOTgraphic}, a figure is inserted directly using +%D \type{\startMPpage ... }\type{\stopMPpage}. +%D +%D A high-level command is provided if some more advance features will +%D be needed in the future and to be able to ensure backward compatibility. + +%D We need to preserve line breaks, otherwise metapost runs into troubles for longer input. +\def\startGNUPLOTpage + {\obeyMPlines\dostartGNUPLOTpage} + +\long\def\dostartGNUPLOTpage#1\stopGNUPLOTpage + {\startMPpage#1\stopMPpage} + + +% TODO: currently, the following definitions are used, +% but the ones below would be preferred + +\def\defineGNUPLOThandle#1#2#3#4#5#6% name; output; suffix; conversion-method; gnuplot's result; final result + {\setvalue{@@GNUPLOT-#1}{{#2}{#3}{#4}{#5}{#6}}} + +\def\@@GNUPLOToutput{\filterfromvalue{@@GNUPLOT-\@@GNUPLOTterminal}51} +\def\@@GNUPLOTsuffix{\filterfromvalue{@@GNUPLOT-\@@GNUPLOTterminal}52} +\def\@@GNUPLOThandle{\filterfromvalue{@@GNUPLOT-\@@GNUPLOTterminal}53} +\def\@@GNUPLOTresult{\filterfromvalue{@@GNUPLOT-\@@GNUPLOTterminal}54} +\def\@@GNUPLOTfinalresult{\filterfromvalue{@@GNUPLOT-\@@GNUPLOTterminal}55} + +% name "set term" suffix conversion (system command) gnuplot's result final result +% (suffix is probably not needed any more since full names were introduced) +\defineGNUPLOThandle + {postscript}{postscript color}{ps}{texmfstart pstopdf --method=raw \GNUPLOTfile-ps.ps} + {\GNUPLOTfile-ps.ps}{\GNUPLOTfile-ps.pdf} +\defineGNUPLOThandle + {ps}{postscript color}{ps}{texmfstart pstopdf -dAutoRotatePages=/PageByPage --method=raw \GNUPLOTfile-ps.ps} + {\GNUPLOTfile-ps.ps}{\GNUPLOTfile-ps.pdf} +\defineGNUPLOThandle + {eps}{postscript color eps}{ps}{texmfstart pstopdf -dEPSCrop \GNUPLOTfile-eps.eps} + {\GNUPLOTfile-eps.eps}{\GNUPLOTfile-eps.pdf} +\defineGNUPLOThandle + {pdf}{pdf}{pdf}{} + {\GNUPLOTfile-pdf.pdf}{\GNUPLOTfile-pdf.pdf} +\defineGNUPLOThandle + {metapost}{mp}{mp}{texmfstart mptopdf \GNUPLOTfile-mp.mp} + {\GNUPLOTfile-mp.mp}{\GNUPLOTfile-mp-0.pdf} +\defineGNUPLOThandle + {mp}{mp}{mp}{texmfstart mptopdf \GNUPLOTfile-mp.mp} + {\GNUPLOTfile-mp.mp}{\GNUPLOTfile-mp-0.pdf} +\defineGNUPLOThandle + {png}{png}{png}{} + {\GNUPLOTfile-png.png}{\GNUPLOTfile-png.png} +\defineGNUPLOThandle + {context}{context textscale \@@GNUPLOT@term@context@textscale}{tex}{} + {\GNUPLOTfile-ctx.tex}{\GNUPLOTfile-ctx.tex} +% \doifnotempty{\@@GNUPLOT@term@context@textscale}{textscale \@@GNUPLOT@term@context@textscale} + +\def\defineGNUPLOTterminal + {\dodoubleargument\dodefineGNUPLOTterminal} + +\def\dodefineGNUPLOTterminal[#1][#2]% + {\doifassignmentelse{#2}% + % define a proper terminal + {}% TODO + % only define a synonym for that terminal + {}% TODO + } + +%D {\sl terminal}: argument to be passed to gnuplot in the form of "set term {\sl terminal}" +%D {\sl defaultoptions}: options to be passed to gnuplot after terminal name: +%D set term {\sl teminal} {\sl defaultoptions} +%D not to be touched by users +%D {\sl suffix}: filename suffix +%D {\sl result}: the file to which gnuplot should output the result +%D set output {\sl result} +%D {\sl convertwith}: command for conversion from gnuplot-generated file to a file that can be read by \CONTEXT; may be empty +%D {\sl finalresult}: file resulting after the conversion to be read by \CONTEXT + +%D \POSTSCRIPT\ terminal +\defineGNUPLOTterminal + [postscript] + [terminal=postscript, + defaultoptions=color, % TODO: only if \setupcolors[state=start] + suffix=ps, + result=\GNUPLOTfile-ps.ps, + % TODO: -dAutoRotatePages=/PageByPage or remove that option from the default ones + convertwith={texmfstart pstopdf --method=raw \GNUPLOTfile-ps.ps}, + finalresult=\GNUPLOTfile-ps.pdf, + ] +%D Define \type{ps} as a synonym for \type{postscript} terminal +\defineGNUPLOTterminal + [ps] + [postscript] + +%D \EPS\ terminal: +%D - same terminal as for \POSTSCRIPT, but slightly different handling +\defineGNUPLOTterminal + [eps] + [terminal=postscript, + defaultoptions=eps color, + suffix=eps, + result=\GNUPLOTfile-eps.eps, + % TODO: -dEPSCrop + convertwith={texmfstart pstopdf -dEPSCrop \GNUPLOTfile-eps.eps}, + finalresult=\GNUPLOTfile-eps.pdf, + ] + +%D \PDF\ terminal +\defineGNUPLOTterminal + [pdf] + [terminal=pdf, + defaultoptions=, + suffix=pdf, + result=\GNUPLOTfile-pdf.pdf, + convertwith=, + finalresult=\GNUPLOTfile-pdf.pdf, + ] + +%D \METAPOST\ terminal: +%D - deprecated: use the \CONTEXT\ terminal instead, +%D which was built starting from the \METAPOST\ one, +%D but improved in many aspects +\defineGNUPLOTterminal + [mp] + [terminal=mp, + defaultoptions=, + suffix=mp, + result=\GNUPLOTfile-mp.mp, + convertwith={texmfstart mptopdf \GNUPLOTfile-mp.mp}, + % TODO: support for multiple graphics + % one would need a switch in mptopdf, so that a single pdf would be created instead of multiple ones + finalresult=\GNUPLOTfile-mp-0.pdf, + ] + +\defineGNUPLOTterminal + [metapost] + [mp] + +%D png terminal: +%D - bitmap +%D - no conversion needed +%D - new version pretty advanced +\defineGNUPLOTterminal + [png] + [terminal=png, + defaultoptions=, + suffix=png, + result=\GNUPLOTfile-png.png, + convertwith=, + finalresult=\GNUPLOTfile-png.png, + ] + +%D \CONTEXT\ terminal (native) +\defineGNUPLOTterminal + [context] + [terminal=context, + defaultoptions=, + suffix=tex, + result=\GNUPLOTfile-ctx.tex, + convertwith=, + finalresult=\GNUPLOTfile-ctx.tex, + ] + +\def\setupGNUPLOTterminal + {\dodoubleargument\dosetupGNUPLOTterminal} + +\def\dosetupGNUPLOTterminal[#1][#2]% + {% TODO + \getparameters[@@GNUPLOT@term@#1@][#2] + % TODO: width & height + % linejoin, linecap - I have to improve this !!! + % \edef\gp:term:context:linejoin{\@@GNUPLOT@term@context@linejoin} + % \edef\gp:term:context:linecap{\@@GNUPLOT@term@context@linecap} + % dashed or solid lines? + \doifsamestringelse{\@@GNUPLOT@term@context@dashed}{yes}% yes or no + {\edef\@@GNUPLOT@term@context@is@dashed{true}}% + {\edef\@@GNUPLOT@term@context@is@dashed{false}}% + % {\edef\gp:term:context:dashed{true}}% + % {\edef\gp:term:context:dashed{false}}% + % % dashlength scale + % \edef\gp:term:context:dashlength{\@@GNUPLOT@term@context@dashlength} + % % linewidth scale + % \edef\gp:term:context:linewidth{\@@GNUPLOT@term@context@linewidth} + } + +\setupGNUPLOTterminal + [context] + [width=default, % *default* (5in) | <dimension> + height=default, % *default* (3in) | <dimension> + linejoin=rounded, % mitered | *rounded* | beveled + linecap=butt, % *butt* | rounded (in gnuplot: round) | squared + dashed=yes, % *yes* | no + dashlength=1, % scaling factor for dash lengths + linewidth=1, % scaling factor for line widths (1.0 means 0.4bp) + textscale=1, % scaling factor for text labels + points=metapost] % *metapost* | tex (Should points be drawn with MetaPost or TeX?) + +% TODO: better scaling +\defineconversion + [gnuplot:pointset] + [{\scale[scale=800]{\mathematics{+}}}, + {\scale[scale=800]{\mathematics{\times}}}, + \mathematics{\ast}, + {\scale[scale=700]{\mathematics{\square}}}, + {\scale[scale=700]{\mathematics{\blacksquare}}}, + \mathematics{\circ}, + \mathematics{\bullet}, + {\scale[scale=900]{\mathematics{\triangleup}}}, + {\scale[scale=900]{\mathematics{\blacktriangle}}}, + {\scale[scale=900]{\mathematics{\triangledown}}}, + {\scale[scale=900]{\mathematics{\blacktriangledown}}}, + {\scale[scale=800]{\mathematics{\lozenge}}}, + {\scale[scale=800]{\mathematics{\blacklozenge}}}%, +% {\rotate[rotation=45]{\mathematics{\square}}}, +% {\rotate[rotation=45]{\mathematics{\blacksquare}}}, + ] + +%\defineGNUPLOTcolor[red] [r=1] +%\defineGNUPLOTcolor[green] [g=1] +%\defineGNUPLOTcolor[blue] [b=1] +%\defineGNUPLOTcolor[magenta][r=1,b=1] +%\defineGNUPLOTcolor[cyan] [g=1,b=1] +%\defineGNUPLOTcolor[yellow] [r=1,g=1] +%\defineGNUPLOTcolor[black] [s=0] +%\defineGNUPLOTcolor[orange] [r=1,g=.3,b=0] +%\defineGNUPLOTcolor[gray50] [s=.5] + +%\defineGNUPLOTcolors +% [default] % from PostScript +% [red,green,blue,magenta,cyan,yellow,black,orange,gray50] + +% TODO: testset is here only temporary & for testing +\setupGNUPLOT[program=gnuplot,\c!terminal=context,\c!options=,\c!pointset=gnuplot:pointset] % colors=postscript + +%D Some additional typescripts which enable us using font "Arial" and "Helvetica" + +%D Pretend the font to be serif as well, so that no "ss" switch is needed +\starttypescript [serif] [helvetica] [name] + \definefontsynonym [Serif] [Helvetica] + \definefontsynonym [SerifBold] [Helvetica-Bold] + \definefontsynonym [SerifItalic] [Helvetica-Oblique] + \definefontsynonym [SerifSlanted] [Helvetica-Oblique] + \definefontsynonym [SerifBoldItalic] [Helvetica-BoldOblique] + \definefontsynonym [SerifBoldSlanted] [Helvetica-BoldOblique] + \definefontsynonym [SerifCaps] [Helvetica] +\stoptypescript + +\starttypescript [gnuplot] [texnansi,ec] + \definetypeface [Helvetica] [rm] [serif] [helvetica] [default] [encoding=\typescripttwo] + \definetypeface [Helvetica] [ss] [sans] [helvetica] [default] [encoding=\typescripttwo] + \definetypeface [Arial] [rm] [serif] [helvetica] [default] [encoding=\typescripttwo] + \definetypeface [Arial] [ss] [sans] [helvetica] [default] [encoding=\typescripttwo] +\stoptypescript + +% TODO: fix for XeTeX +\usetypescript[gnuplot][ec] + +\stopmodule + +\protect \doifnotmode{demo}{\endinput} + + +\starttext + +\startGNUPLOTscript[exp] +set key bottom +set format x "%.1f" +set format y "%.1f" +set style fill solid 0.25 noborder +plot [0:3] 2/sqrt(pi)*exp(-x**2) t '$\frac{2}{\sqrt{\pi}}e^{-x^2}$' with filledcurves x1 lt 3, erf(x) lc 3 lw 2 +\stopGNUPLOTscript + +\useGNUPLOTgraphic[exp][width=.7\textwidth] + + +\startGNUPLOTinclusions + set title "trigonometry" +\stopGNUPLOTinclusions + +\startGNUPLOTscript[sin] + plot sin(x) +\stopGNUPLOTscript + +\startGNUPLOTscript[cos] + plot cos(x) +\stopGNUPLOTscript + +\useGNUPLOTgraphic[sin] \endgraf +\useGNUPLOTgraphic[cos] \endgraf +\useGNUPLOTgraphic[cos] \endgraf + +\setupGNUPLOT[terminal=ps] \useGNUPLOTgraphic[sin][object=no,height=2cm] \blank +%setupGNUPLOT[terminal=pdf] \useGNUPLOTgraphic[sin][object=no,height=2cm] \blank +%setupGNUPLOT[terminal=png] \useGNUPLOTgraphic[sin][object=no,height=2cm] \blank +\setupGNUPLOT[terminal=mp] \useGNUPLOTgraphic[sin][object=no,height=2cm,options=color] \blank + +\stoptext + diff --git a/Master/tlpkg/bin/ctan2tds b/Master/tlpkg/bin/ctan2tds index 46a4406f83c..e8aed161447 100755 --- a/Master/tlpkg/bin/ctan2tds +++ b/Master/tlpkg/bin/ctan2tds @@ -128,6 +128,7 @@ chdir $startdir || die "chdir($startdir) failed: $!"; # back to raw 'context-construction-plan', "&MAKEcopy", 'context-degrade', "&MAKEcopy", 'context-french', "&MAKEcopy", + 'context-gnuplot', "&MAKEcopy", 'context-letter', "&MAKEcopy", 'context-lettrine', "&MAKEcopy", 'context-lilypond', "&MAKEcopy", diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index e94fe284b86..7040182660e 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -56,6 +56,7 @@ my @WorkingTLP = qw( computational-complexity confproc constants context-account context-bnf context-chromato context-construction-plan context-degrade context-french + context-gnuplot context-letter context-lettrine context-lilypond context-mathsets context-taspresent context-typearea context-vim diff --git a/Master/tlpkg/tlpsrc/collection-context.tlpsrc b/Master/tlpkg/tlpsrc/collection-context.tlpsrc index 6397872ff14..d0d4ecbfa7b 100644 --- a/Master/tlpkg/tlpsrc/collection-context.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-context.tlpsrc @@ -2,6 +2,7 @@ name collection-context category Collection shortdesc ConTeXt format longdesc Hans Hagen's powerful ConTeXt system, http://pragma-ade.com. +longdesc Also includes third-party ConTeXt packages. depend context depend jmn depend lmextra @@ -12,6 +13,7 @@ depend context-chromato depend context-construction-plan depend context-degrade depend context-french +depend context-gnuplot depend context-letter depend context-lettrine depend context-lilypond diff --git a/Master/tlpkg/tlpsrc/context-gnuplot.tlpsrc b/Master/tlpkg/tlpsrc/context-gnuplot.tlpsrc new file mode 100644 index 00000000000..8ff4c7e4703 --- /dev/null +++ b/Master/tlpkg/tlpsrc/context-gnuplot.tlpsrc @@ -0,0 +1,2 @@ +name context-gnuplot +category Package |