#309 Improve latex text length (and height!) estimation

open
nobody
None
5
2011-11-08
2011-11-08
greenux
No

I had kind of trouble using latex commands in gnuplot with epslatex
terminal and build me a workaround by creating one file with the latex
command, another file only with placeholder create by latex with the
estimated size from latex and then combined them. This is kind of
stupid. Instead it would be much better to improve the gnuplot source
code.
I finally made a new strlen_tex() function in term.c (see below - I'm
not really good in C programming!!!) to estimate the length of the
latex code correctly by running latex. (I will change term->h_char to
1 to get more precise results).
Now I have the same problem for the height (especially for the key
box), but there is no strheight_tex() function, only a term->v_char.
The correct term->v_char should be a function depend on the heighest
key entry (the entries heights can differ e. g. if using subscript or
superscript!). Because of that I would like to propose to change the
gnuplot source in a way that each terminal provides a strheight()
function instead of t->v_char. Than for each element the height is
estimated by the strheight(char *entry) function. For constant height
the strheight() function returns term->v_char, but in other cases it
can also return the exact value.
The key box height can now be calculated by getting the highest value
of strheight() for each entry. The same holds for xtics, ytics, ...
Running latex doesn't take much time, but it improves the result very
much!
This change affects a lot of source code, but it improves the
possibilities for all terminals and the results!
I would be very thankful if someone who is much better in C
programming then me could make these changes!

/*
* Run latex to estimate the correct strlen no matter what is the
text
*/
int
strlen_tex(const char *str)
{
const char *s = str;
char ch;
int len = 0;
int i = 0;
float a; //result array

//Write latex code to file
FILE *texfile = fopen("gnuplot_estimate_strlen_tex.tmp","w");
fprintf(texfile,"\\documentclass{article}\n"); //Maybe a minimal
class would increase speed

//Read packages from file
FILE *pkgfile = fopen("packages.tex","r"); //load all required
packages from file in same directory, later a terminal option could be
used
while ( 1 )
{
ch = fgetc ( pkgfile );
if ( ch == EOF )
break;
else
fputc ( ch, texfile );
}
fclose(pkgfile);

fprintf(texfile,"\\newwrite\\tempfile\n");
fprintf(texfile,"\\makeatletter\n");
fprintf(texfile,"\\newcommand*{\\printlength}[1]{\\strip@pt\ \dimexpr(#1)\\relax}\n");
fprintf(texfile,"\\makeatother\n\n");
fprintf(texfile,"\\begin{document}\n");
fprintf(texfile,"\\newlength{\\mytextwidth}\n \\newlength{\ \mytextheight}\n");
fprintf(texfile,"\\immediate\\openout\ \tempfile=gnuplot_estimate_strlen_tex_out.tmp\n");

fprintf(texfile,"\\renewcommand{\\myobject}{%s}\n",s); //Write the
text to latex file

fprintf(texfile,"\\settowidth{\\mytextwidth}{\\myobject}\n");
//fprintf(texfile,"\\settoheight{\\mytextheight}{\\hbox{\ \myobject}}\n"); //not used only to know what to do to get the correct
height
fprintf(texfile,"\\immediate\\write\\tempfile{\\printlength{\ \mytextwidth}}\n");
fprintf(texfile,"\\immediate\\closeout\\tempfile\n");
fprintf(texfile,"\\end{document}\n");
fclose(texfile); /*done!*/

//Run latex
int exitcode = system("pdflatex -draftmode -interaction=batchmode
\"gnuplot_estimate_strlen_tex.tmp\""); //todo: use macros instead of
filename here

FILE *ofile = fopen ("gnuplot_estimate_strlen_tex_out.tmp","r");
//todo: use macros instead of filename here, maybe tmp-directory
if (!ofile) {
/* can't open, stop processing */
}
a=0.0;
int returncodefscanf = fscanf(ofile,"%f",&a);
fclose(ofile);
len=a/5; //Depends on what latex returns, currently not exact!
fprintf(stderr,"Size from latex is %f - Estimate length is %d
\n",a,len); //debug information

return len;
}

Discussion

  • greenux
    greenux
    2011-11-08

    • summary: Improve latx text length (and height!) estimation --> Improve latex text length (and height!) estimation
     
  • Ethan Merritt
    Ethan Merritt
    2011-11-13

    We don't want to make gnuplot dependent on running latex, so this is not really a practical solution.

    I agree with you fully that it would be nice if gnuplot knew exactly how much space each string would occupy both horizontally and vertically. Unfortunately the list of output devices for which this is possible is very short. In fact, the only terminal driver for which I can see how to do it is gd.trm, all the others do their text writing out of the sight of the gnuplot core code.

    Perhaps if you showed what your original problem was, someone might have a simpler suggested solution?

     
  • greenux
    greenux
    2011-11-14

    Of course it is not the best solution to make dependent on latex, but latex is the only program exactly knowing the size of a string. Maybe this could be handled by an optional terminal, which requires latex - this way the "default" gnuplot is independent of latex.

    I don't have a special problem. But for all plots I do, I want to use in latex with epslatex terminal. I use my own definied symbols and commands included from an additional latex file. When using different fontsizes I have to change all the "workaround" setting like keyspacing and label offset, ... when reusing images for slides and other papers. Or only changing the fontsize later.
    I think this is a very common problem for everyone who includes gnuplots in latex with special latex commands/symbols. My problem is, that I don't really know how to write good C programs to contribute this to the gnuplot development.

     
  • Peter Hedwig
    Peter Hedwig
    2011-11-30

    It is possible to use the TikZ terminal together with the gnuplottex package to get good estimates for the font size. Here is a small example:

    \documentclass[10pt,a4paper]{article}
    \usepackage[T1]{fontenc}
    \usepackage{textcomp}
    \usepackage[utf8x]{inputenc}

    \usepackage{gnuplot-lua-tikz}
    \usepackage{gnuplottex}

    \makeatletter
    \def\gpcalccharsize{%
    \pgfinterruptboundingbox%
    \pgfsys@begininvisible%
    \node at (0,0) {%
    \global\gphcharsize=\fontcharwd\font`0%
    \global\gpvcharsize=\fontcharht\font`0%
    \global\advance\gpvcharsize by \fontchardp\font`g%
    };%
    \pgfsys@endinvisible%
    \endpgfinterruptboundingbox%
    }
    \makeatother

    \tikzset{gnuplot/.append style={execute at begin picture=\gpcalccharsize}}

    \tikzset{gp node left/.style={anchor=mid west,yshift=-.12ex,outer sep=0pt,inner sep=0pt}}
    \tikzset{gp node center/.style={anchor=mid,yshift=-.12ex,outer sep=0pt,inner sep=0pt}}
    \tikzset{gp node right/.style={anchor=mid east,yshift=-.12ex,outer sep=0pt,inner sep=0pt}}

    \begin{document}

    \begin{tikzpicture}[gnuplot,font=\large]
    \begin{gnuplot}[terminal=tikz,%
    terminaloptions={solid nopic charsize \the\gphcharsize,\the\gpvcharsize}]
    test
    \end{gnuplot}
    \end{tikzpicture}

    \end{document}

    During the TeX run the font size will be measured and passed as a terminal option parameter. The generated TikZ code will be read back and compiled in the same run. You also have to run (pdf)latex with the option "-shell-escape" so that gnuplot can be called from within latex.

    The definitions of the \gpcalccharsize makro and the various node styles are already part of the gnuplot-lua-tikz style file. But the changes I made here give slightly better results ;)