From: Dimitrios Eftaxiopoulos Date: Sat, 7 Feb 2015 19:26:59 +0000 (+0200) Subject: Imported Upstream version 2.3.2 X-Git-Tag: archive/raspbian/2.5-2+rpi1^2~26^2~10 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=33a8b6c3787cda4b38f7733a5a4f3ad119a3fd34;p=mathgl.git Imported Upstream version 2.3.2 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a4076e..b369da1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 2.8.9) +if(POLICY CMP0043) + cmake_policy(SET CMP0043 OLD) +endif() project( MathGL ) @@ -69,6 +72,11 @@ option(enable-all-swig "Enable all SWIG based interfaces") option(enable-rvalue "Enable move constructor support (need C++11)" OFF) option(enable-pthread "Enable POSIX threads support" OFF) option(enable-openmp "Enable OpenMP support" ON) + +if(enable-pthread AND enable-openmp) + message(SEND_ERROR "You can't enable POSIX threads and OpenMP at the same time!") +endif(enable-pthread AND enable-openmp) + option(enable-lgpl "Enable only LGPL part of MathGL") option(enable-mgl2 "Use names 'libmgl2-*' instead of 'libmgl-*'") option(enable-ltdl "Enable loading modules support") @@ -116,6 +124,7 @@ MGL_DEPENDENT_OPTION(enable-octave-install "Octave interface will install for al include_directories( ${MathGL_SOURCE_DIR}/include ${MathGL_BINARY_DIR}/include) set(MGL_INCLUDE_PATH "${CMAKE_INSTALL_PREFIX}/include/mgl2") set(MGL_CGI_PATH "${CMAKE_INSTALL_PREFIX}/share/mathgl" CACHE STRING "Set CGI install directory") +set(MGL_DEF_FONT "STIX" CACHE STRING "Set default font name") if(NOT WIN32) # set(MGL_CGI_PATH "${CMAKE_INSTALL_PREFIX}/share/mathgl") diff --git a/ChangeLog.txt b/ChangeLog.txt index 5c2363f..716ad27 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,4 +1,14 @@ -2.3.1 Released 20 October 2014 +2.3.2 Released 2 February 2015 + +* Update mgltex (thanks to Diego Sejas Viscarra) +* Add reading files with complex numbers by 'read' command. +* Parallelize reading textual data files. +* Add 'i','j','k' variables for data filling. +* Add saving images in QMathGL even if corresponding format support is disabled. +* Add cmake option MGL_DEF_FONT to change default font name or use built-in one (if MGL_DEF_FONT is empty). +* Compatibility changes and bugfixes. + +2.3.1 Released 21 October 2014 * Add MGL command 'load' for loading MGL commands from external DLL (or .so) module. * Add Logo() function to draw bitmap (logo), which is stretched along whole axis range diff --git a/examples/full_test.cpp b/examples/full_test.cpp index c6605dc..4f2a465 100644 --- a/examples/full_test.cpp +++ b/examples/full_test.cpp @@ -64,7 +64,6 @@ void mgls_prepare3v(mglData *ex, mglData *ey, mglData *ez); void save(mglGraph *gr,const char *name,const char *suf); void test(mglGraph *gr) { -// gr->Rotate(40,60); gr->Fog(1); gr->Box(); return; mglParse par; par.Execute(gr,"load '/home/balakin/mathgl-code/mathgl-2x/build/examples/libmgl_module.so':baxis\n"); // par.Execute(gr,"subplot 1 1 0:#rotate 40 60\nperspective 1.22:box:axis\n"); @@ -365,7 +364,7 @@ void smgl_fexport(mglGraph *gr) // test file export gr->WriteOBJ("fexport.obj"); gr->WritePRC("fexport.prc"); gr->WriteJSON("fexport.json"); - + gr->ExportMGLD("fexport.mgld"); gr->Clf(); gr->ImportMGLD("fexport.mgld"); @@ -417,7 +416,11 @@ int main(int argc,char **argv) { mgl_set_test_mode(true); test(gr); time(&en); printf("time is %g sec\n",difftime(en,st)); +#if MGL_HAVE_PNG gr->WritePNG("test.png","",false); +#else + gr->WriteBMP("test.bmp"); +#endif gr->WriteSVG("test.svg"); gr->WriteEPS("test.eps"); printf("Messages:%s\n",gr->Message()); diff --git a/include/config.h.in b/include/config.h.in index de1ea33..51d3730 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -3,6 +3,12 @@ #define MGL_USE_DOUBLE ${MGL_USE_DOUBLE} +#ifdef WIN32 // a man ask to use built-in font under Windows +#define MGL_DEF_FONT_NAME "" +#else +#define MGL_DEF_FONT_NAME "${MGL_DEF_FONT}" +#endif + #if defined(_MSC_VER) || defined(__BORLANDC__) #define MGL_SYS_NAN 0 #define MGL_HAVE_TYPEOF 0 diff --git a/include/mgl2/addon.h b/include/mgl2/addon.h index b083469..5896c36 100644 --- a/include/mgl2/addon.h +++ b/include/mgl2/addon.h @@ -40,9 +40,9 @@ void MGL_EXPORT mgl_fft_freq(double *freq,long nn); /// Remove double spaces from the string void MGL_EXPORT mgl_strcls(char *str); /// Get position of substring or return -1 if not found -int MGL_EXPORT_PURE mgl_strpos(const char *str,char *fnd); +long MGL_EXPORT_PURE mgl_strpos(const char *str,char *fnd); /// Get position of symbol or return -1 if not found -int MGL_EXPORT_PURE mgl_chrpos(const char *str,char fnd); +long MGL_EXPORT_PURE mgl_chrpos(const char *str,char fnd); /// Get uncommented string from file (NOTE: it is not thread safe!!!) MGL_EXPORT char *mgl_fgetstr(FILE *fp); diff --git a/include/mgl2/base.h b/include/mgl2/base.h index dea1383..40244fc 100644 --- a/include/mgl2/base.h +++ b/include/mgl2/base.h @@ -44,7 +44,7 @@ mglPoint GetZ(HCDT z, int i, int j, int k=0); template class mglStack { T** dat; - size_t pb; ///< size of buffer (real size is 2^pb == 1<>pb); if(num>np) { dat = (T**)realloc(dat, num*sizeof(T*)); np=num; } - for(size_t i=m;i &operator=(const mglStack &st) { pb=st.pb; clear(); reserve(st.n); - for(size_t i=0;i #if defined(_MSC_VER) -#if (_MSC_VER<1800) +#if (_MSC_VER<=1800) #define collapse(a) // MSVS don't support OpenMP 3.* #define strtoull _strtoui64 #define hypot _hypot @@ -177,16 +177,6 @@ typedef float mreal; #define mgl_sign(a) ((a)<0 ? -1:1) #endif //----------------------------------------------------------------------------- -#define SMOOTH_NONE 0 -#define SMOOTH_LINE_3 1 -#define SMOOTH_LINE_5 2 -#define SMOOTH_QUAD_5 3 -//----------------------------------------------------------------------------- -#define MGL_HIST_IN 0 -#define MGL_HIST_SUM 1 -#define MGL_HIST_UP 2 -#define MGL_HIST_DOWN 3 -//----------------------------------------------------------------------------- enum{ // types of predefined curvelinear coordinate systems mglCartesian = 0, // no transformation mglPolar, @@ -274,8 +264,14 @@ extern uint64_t mgl_mask_val[16]; #include #if MGL_USE_DOUBLE typedef double _Complex mdual; +#ifndef _Complex_I +#define _Complex_I (double _Complex){0, 1} +#endif #else typedef float _Complex mdual; +#ifndef _Complex_I +#define _Complex_I (float _Complex){0, 1} +#endif #endif #define mgl_abs(x) cabs(x) #endif diff --git a/include/mgl2/font.h b/include/mgl2/font.h index 2e08a01..dcb23b5 100644 --- a/include/mgl2/font.h +++ b/include/mgl2/font.h @@ -38,12 +38,6 @@ #define MGL_COLOR_MASK 0xffffff00 #define MGL_FONT_STYLE 0x3f000000 //----------------------------------------------------------------------------- -#ifdef WIN32 // a man ask to use built-in font under Windows -#define MGL_DEF_FONT_NAME 0 -#else -#define MGL_DEF_FONT_NAME "STIX" -#endif -//----------------------------------------------------------------------------- struct mglGlyphDescr { wchar_t id; ///< Unicode ID for glyph diff --git a/include/mgl2/opengl.h b/include/mgl2/opengl.h index c95a310..a859043 100644 --- a/include/mgl2/opengl.h +++ b/include/mgl2/opengl.h @@ -30,7 +30,7 @@ public: void SetQuality(int =0) { Quality=2; } void Finish(); - void SetSize(int ,int ) {} + void SetSize(int ,int ,bool clf=true) { if(clf) Clf(); } void View(mreal tetX,mreal tetY,mreal tetZ); void Zoom(mreal x1, mreal y1, mreal x2, mreal y2); /* int NewFrame(); @@ -43,6 +43,7 @@ public: void Light(int n, bool enable); void AddLight(int n,mglPoint r,mglPoint d, char c='w', mreal bright=0.5, mreal ap=0); void Clf(mglColor Back=NC); + void Clf(const char *col); protected: // provide fastest variant for usual points (not glyphs or marks) diff --git a/include/mgl2/parser.h b/include/mgl2/parser.h index 0fe0f23..3ff6fa4 100644 --- a/include/mgl2/parser.h +++ b/include/mgl2/parser.h @@ -100,6 +100,7 @@ public: bool Stop; ///< Stop command was. Flag prevent further execution mglCommand *Cmd; ///< Table of MGL commands (can be changed by user). It MUST be sorted by 'name'!!! long InUse; ///< Smart pointer (number of users) + const mglBase *curGr; ///< Current grapher mglParser(bool setsize=false); virtual ~mglParser(); diff --git a/include/mgl2/qmathgl.h b/include/mgl2/qmathgl.h index e416d7d..53241df 100644 --- a/include/mgl2/qmathgl.h +++ b/include/mgl2/qmathgl.h @@ -181,6 +181,7 @@ protected: mglDraw *draw; ///< Class for drawing -- need to call directly due to inheritance mechanism QString mousePos; ///< Last mouse position QPixmap pic; ///< Pixmap for drawing (changed by update) + QImage img; ///< Last used HQ image double tet, phi; ///< Rotation angles double per; ///< Value of perspective ( must be in [0,1) ) bool alpha; ///< Transparency state @@ -223,7 +224,7 @@ public: }; //----------------------------------------------------------------------------- /// Convert bitmap from mglCanvasWnd to QPixmap -void mglConvertFromGraph(QPixmap &pic, mglCanvas *gr, uchar **buf); +void mglConvertFromGraph(QPixmap &pic, mglCanvas *gr, uchar **buf, QImage *out=NULL); /// Make menu, toolbars and return popup menu for MainWindow MGL_EXPORT QMenu *mglMakeMenu(QMainWindow* Wnd, QMathGL* QMGL, QSpinBox*& tet, QSpinBox*& phi); //----------------------------------------------------------------------------- diff --git a/json/mathgl.Graph.js b/json/mathgl.Graph.js index 5ae6984..d505b47 100644 --- a/json/mathgl.Graph.js +++ b/json/mathgl.Graph.js @@ -25,8 +25,8 @@ mathgl.Graph = function(canvas, backend) { this.__fov = 0; // perspective this.__x1 = 0; this.__y1 = 0; this.__z1 = 0; this.__x2 = 1; this.__y2 = 1; this.__z2 = 1; -} - + this.__activeTimeoutHandlers = []; +}; /** * Initialize current view by given MGL script. @@ -47,6 +47,28 @@ mathgl.Graph.prototype.init = function(mgl) { this.__view.attachCanvas(this.__canvas); } +/** + * Method uses to wrap native JS setTimeout function to make possible deactivate active callbacks in destroy method + * + * @param func {Function} Callback function, will be executed after delay + * @param delay {Number} Delay before callback call + */ +mathgl.Graph.prototype.__setTimeout = function(func, delay) { + var me = this; + var timeoutFunc = function() { + func.call(); + var index = me.__activeTimeoutHandlers.indexOf(this.setTimeoutId); + if (index > -1) { + // remove timeout from activeTimeoutHandlers list + me.__activeTimeoutHandlers.splice(index, 1); + } + } + + var timeoutId = setTimeout(mathgl.bind(timeoutFunc, timeoutFunc), delay); + // keep timeout handler inside function + timeoutFunc.setTimeoutId = timeoutId; + this.__activeTimeoutHandlers.push(timeoutId); +}; /** * Load graph state from JSON string. @@ -136,7 +158,7 @@ mathgl.Graph.prototype.__renderStart = function() { if (!this.__isDraftRenderingInScheduled) { // enqueue draft rendering step this.__isDraftRenderingInScheduled = true; - setTimeout(mathgl.bind(this.__renderDraft, this), 0); + this.__setTimeout(mathgl.bind(this.__renderDraft, this), 0); } } @@ -149,7 +171,7 @@ mathgl.Graph.prototype.__renderDraft = function() { // enqueue precise rendering step if (!this.__isPreciseRenderingScheduled) { this.__isPreciseRenderingScheduled = true; - setTimeout(mathgl.bind(this.__renderPrecise, this), this.__preciseRenderingDelay); + this.__setTimeout(mathgl.bind(this.__renderPrecise, this), this.__preciseRenderingDelay); } this.__draftFinishedTimestamp = new Date(); } @@ -167,7 +189,7 @@ mathgl.Graph.prototype.__renderPrecise = function() { // rechedule pricese rendering if it is not var current = new Date(); if (current - this.__draftFinishedTimestamp < this.__preciseRenderingDelay) { - setTimeout(mathgl.bind(this.__renderPrecise, this), this.__preciseRenderingDelay - (current - this.__draftFinishedTimestamp)); + this.__setTimeout(mathgl.bind(this.__renderPrecise, this), this.__preciseRenderingDelay - (current - this.__draftFinishedTimestamp)); return; } this.__drawMesh(true); @@ -626,6 +648,11 @@ mathgl.Graph.prototype.redraw = function() { } mathgl.Graph.prototype.destroy = function() { + // clear active timeouts + for (var i = 0, l = this.__activeTimeoutHandlers.length; i ${mgl_pkg_dir} COMMAND ${oct_tar} cpzf mathgl.tar.gz ${pkg_name} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/lang DEPENDS mgl-oct diff --git a/mgltex/mgltex.dtx b/mgltex/mgltex.dtx index 77e480a..34dedae 100644 --- a/mgltex/mgltex.dtx +++ b/mgltex/mgltex.dtx @@ -18,20 +18,14 @@ % \fi % % \iffalse -%\def\mgl@name{mgltex} -%\def\mgl@date{2014/09/16} -%\def\mgl@version{1.0} -%\def\mgl@description{Embed MGL code into LaTeX documents} -% +% %\NeedsTeXFormat{LaTeX2e} -%\ProvidesPackage{\mgl@name}[\mgl@date\space v.\mgl@version\space\mgl@description] +%\ProvidesPackage{mgltex}[/2014/11/22 v2.0 Embed MGL scripts in LaTeX documents] % %<*driver> \documentclass{ltxdoc} -\usepackage{mgltex} -\def\linefill#1{% - \leavevmode\leaders\hrule height #1\hfill\kern0em% -} +\usepackage{color} +\usepackage[comments]{mgltex} \EnableCrossrefs \CodelineIndex \RecordChanges @@ -41,7 +35,7 @@ % % \fi % -% \CheckSum{0} +% \CheckSum{1297} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z @@ -60,10 +54,23 @@ % Right brace \} Tilde \~} % % \changes{v1.0}{2014/09/27}{Initial version} +% \changes{v.2.0}{2014/11/15}{Possible bugfix by adding \texttt{\textbackslash expandafter} to commands to ignore/write lines of MGL code} +% \changes{v.2.0}{2014/11/15}{Add environment \texttt{mglsignature} that adds a commentary every MGL script} +% \changes{v.2.0}{2014/11/15}{Eliminate line ignoring commands to create more elegant scripts, due to the a new command that adds comments to the scripts} % % \GetFileInfo{mgltex.sty} % -% \DoNotIndex{} +% \DoNotIndex{\def,\bgroup,\egroup,\newcommand,\newenvironment,\\,\@onlypreamble,\@undefined,\@vobeyspaces,\list} +% \DoNotIndex{\if,\else,\fi,\begingroup,\endgroup,\end,\edef,\xdef,\gdef,\scapechar,\active,\arabic,\catcode,\bfseries} +% \DoNotIndex{\@flushglue,\@for,\@ifnextchar,\@makeother,\{,\},\^,\ ,\AtBeginDocument,\AtEndDocument,\centering} +% \DoNotIndex{\closein,\closeout,\csname,\endcsname,\CurrentOption,\DeclareGraphicsExtensions,\define@key,\DeclareOption} +% \DoNotIndex{\detokenize,\do,\dospecials,\endlinechar,\endlist,\escapechar,\ExecuteOptions,\expandafter,\footnotesize} +% \DoNotIndex{\framebox,\Gin@extensions,\Huge,\ifeof,\IfFileExists,\ifx,\immediate,\include,\includegraphics,\item,\itemsep} +% \DoNotIndex{\itshape,\jobname,\labelsep,\leftskip,\let,\long,\mbox,\newcounter,\newread,\newtoks,\newwrite,\noexpand} +% \DoNotIndex{\obeyspaces,\openin,\openout,\PackageError,\PackageWarning,\parfillskip,\parindent,\parskip} +% \DoNotIndex{\PassOptionsToPackage,\ProcessOptions,\read,\relax,\RequirePackage,\rightskip,\setcounter,\setkeys,\setlength} +% \DoNotIndex{\space,\stepcounter,\string,\TeX,\the,\vbox,\verbatim@font,\write,\z@,\z@skip,\newif,\PackageInfo,\today} +% \DoNotIndex{\obeylines,\or\ifcase,\small} % % \title{The \textsf{\mglTeX} package\thanks{This document corresponds to \textsf{\mglTeX}~\fileversion, dated \filedate.}} % \author{Diego Sejas Viscarra\\\texttt{diego.mathematician@gmail.com}} @@ -71,7 +78,9 @@ % \maketitle % % \begin{abstract} -% \noindent +% \noindent MathGL is a fast and efficient library by Alexey Balakin for the creation of high-quality publication-ready scientific graphics. Although it defines interfaces for many programming languages, it also implements its own programming language, called \emph{MGL}, which can be used independently. With the package \textsf{\mglTeX}, MGL scripts can be embedded within any \LaTeX{} document, and the corresponding images are automatically created and included. + +% This manual documents the use of the commands and environments of~\mglTeX. % \end{abstract} % % \section{Introduction} @@ -94,12 +103,19 @@ % \begin{itemize} % \item |draft|: The generated images won't be included in the document. This option is useful when fast compilation of the document is needed. % \item |final|: This overrides the |draft| option. +% \item |on|: To create the MGL scripts and corresponding images of the document every time \LaTeX{} is run. +% \item |off|: To avoid creating the MGL scripts and corresponding images of the document, but still try to include the images. +% \item |comments|: To allow the contents of the |mglcomment| environments to be shown in the \LaTeX{} document. +% \item |nocomments|: To not show the contents of the |mglcomment| environments in the \LaTeX{} document. % \item |png|, |jpg|, |jpeg|: To export images to the corresponding bitmap format. % \item |eps|, |epsz|: To export to uncompressed/compressed EPS format as primitives. % \item |bps|, |bpsz|: To export to uncompressed/compressed EPS format as bitmap. % \item |pdf|: To export to 3D PDF format. +% \item |tex|: To export to \LaTeX{}/\emph{tikz} document. % \end{itemize} -% It must be noted that the options that specify the format to save the images are exclusive, in the sense that if one specifies more than one format, only the last one will be used. +% It must be noted that the options |on| and |off| are exclusive, in the sense that if one specifies both of them, only the last one will be used. Likewise, the options that specify the format to save the graphics are exclusive. +% +% Observe the option |off| is useful to save compilation time of a document. For example, if the graphics of an article are in final version, instead of compilling them over and over again every time \LaTeX{} runs, they can be created only once with the |on| option, and then only included (but not recompiled) with the |off| option. % % The are two ways to compile a document with \textsf{\mglTeX}: The first way is to run % \begin{center} @@ -164,21 +180,73 @@ % \end{tabular} % \end{center} % +% \DescribeEnv{mglcommon} This is used to create a common ``setup'' script that will be executed together with each of the other scripts. It is useful to define constants, parameters, etc. that will be available to every script. +% \begin{center} +% \begin{tabular}{l} +% \hline\\[-0.75em] +% |\begin{mglcommon}|\\[0.5em] +% \hss\meta{MGL code}\hss\\[0.5em] +% |\end{mglcommon}|\\[0.25em] +% \hline +% \end{tabular} +% \end{center} +% +% For example, one could make +% \begin{verbatim} +% \begin{mglcommon} +% define gravity 9.81 # [m/s^2] +% \end{mglcommon} +% \end{verbatim} +% to make the constant \emph{gravity} available to every script. +% +% Observe this environment should be used only to define constants, parameters and things like that, but not graphical objects like axis or grids, because every image created with the |mgl| environment clears every graphical object before creating the image.\footnote{This problem occurs only with the \texttt{mgl} environment, so you could use \texttt{mglcommon} to create many graphics with the same axis, grid, etc., with environments like \texttt{mglcode}, but in that case the best option is to use the \texttt{mglsetup} environment together with the \texttt{\textbackslash{}mglplot} command.} +% +% \DescribeEnv{mglsignature} This environment is used to declare a signature (or commentary) that will be included at the beginning of every script generated by \mglTeX. It is verbatim-like environment, so no \LaTeX{} cammand will be executed, but copied literally. However, the default signature is ``This script was generated from \meta{document}.mgl on date \meta{today}''. +% \begin{center} +% \begin{tabular}{l} +% \hline\\[-0.75em] +% |\begin{mglsignature}|\\[0.5em] +% \hss\meta{Signature for MGL scripts}\hss\\[0.5em] +% |\end{mglsignature}|\\[0.25em] +% \hline +% \end{tabular} +% \end{center} +% +% \DescribeEnv{mglcomment} This environment is used to embed commentaries in the \LaTeX{} document. The commentary won't appear in the case of the user passing the option |nocomments| to the package, but it will be written \emph{verbatim} is the user passes the option |comments|. +% \begin{center} +% \begin{tabular}{l} +% \hline\\[-0.75em] +% |\begin{mglcomment}|\\[0.5em] +% \hss\meta{Commentary}\hss\\[0.5em] +% |\end{mglcomment}|\\[0.25em] +% \hline +% \end{tabular} +% \end{center} +% In the case of the user allowing commentaries, this will result in the appearance of the following commentary in the \LaTeX{} document: +% \begin{center} +% \makeatletter +% \verbatim@font +% \makeatother +% <------------------ MGL comment ------------------>\\ +% \meta{Commentary}\\ +% <------------------ MGL comment ------------------>\\ +% \end{center} +% % \subsection{Fast creation of graphics} -% \noindent\textsf{\mglTeX} defines a convenient way to work with many graphics that have exactly the same settings (for example, same angles of rotation, same type of grid, etc.): instead of writing repetitive code every time it's needed, it can be stored in memory with the |mglplotsettings| environment, and then can be used when needed with the |\mglplot| command. +% \noindent\textsf{\mglTeX} defines a convenient way to work with many graphics that have exactly the same settings (for example, same angles of rotation, same type of grid, etc.): instead of writing repetitive code every time it's needed, it can be stored in memory with the |mglsetup| environment, and then can be used when needed with the |\mglplot| command. % -% \DescribeEnv{mglplotsettings} This environment stores its contents in memory for later use. It accepts one mandatory argument, which is a keyword (name) to be associated to the corresponding block of code, so different blocks of code can be stored with different names. +% \DescribeEnv{mglsetup} This environment stores its contents in memory for later use. It accepts one optional argument, which is a keyword (name) to be associated to the corresponding block of code, so different blocks of code can be stored with different names. % \begin{center} % \begin{tabular}{l} % \hline\\[-0.75em] -% |\begin{mglplotsettings}|\marg{keyword}\\[0.5em] +% |\begin{mglsetup}|\oarg{keyword}\\[0.5em] % \hss\meta{MGL code}\hss\\[0.5em] -% |\end{mglplotsettings}|\\[0.25em] +% |\end{mglsetup}|\\[0.25em] % \hline % \end{tabular} % \end{center} % -% \DescribeMacro{\mglplot} This command is used for fast generation of graphics with default settings, and can be used in parallel with the |mglplotsettings| environment. It accepts one mandatory argument which consists of MGL instructions, separated by the symbol ``:'', which can span through various text lines. It also accepts the same optional arguments as the |mgl| environment, plus an additional one, called |settings|, which can be used to specify a keyword used in a |mglplotsettings| environment. If the |settings| option is specified, the code in the mandatory argument will be appended to the block of code of the corresponding |mglplotsettings| environment. +% \DescribeMacro{\mglplot} This command is used for fast generation of graphics with default settings, and can be used in parallel with the |mglsetup| environment. It accepts one mandatory argument which consists of MGL instructions, separated by the symbol ``:'', which can span through various text lines. It also accepts the same optional arguments as the |mgl| environment, plus an additional one, called |settings|, which can be used to specify a keyword used in a |mglsetup| environment. If the |settings| option is specified, the code in the mandatory argument will be appended to the block of code of the corresponding |mglsetup| environment. % \begin{center} % \begin{tabular}{l} % \hline\\[-0.75em] @@ -242,6 +310,81 @@ % \end{center} % This command must be used in the preamble of the document, since the first MGL script is created at the moment of the |\begin{document}| command; trying to use it somewhere else will issue an error. On the other hand, it is the responsibility of the user to create the \meta{directory}, since \textsf{\mglTeX} won't do it automatically. % +% \DescribeMacro{\mglquality} This command can be used to specify the quality for the graphics created with \mglTeX. An info message specifying the characteristics of the chosen quality is printed in the .log file. +% \begin{center} +% \begin{tabular}{l} +% \hline\\[-0.75em] +% |\mglquality|\marg{quality}\\[0.25em] +% \hline +% \end{tabular} +% \end{center} +% The available qualities are described below: +% \begin{center} +% \begin{tabular}{cl} +% \hline +% Quality & Description\\ +% \hline +% \hline +% $0$ & No face drawing (fastest)\\ +% \hline +% $1$ & No color interpolation (fast)\\ +% \hline +% $2$ & High quality (normal)\\ +% \hline +% $3$ & High quality with 3d primitives (not implemented yet)\\ +% \hline +% $4$ & No face drawing, direct bitmap drawing (low memory usage)\\ +% \hline +% $5$ & No color interpolation, direct bitmap drawing (low memory usage)\\ +% \hline +% $6$ & High quality, direct bitmap drawing (low memory usage)\\ +% \hline +% $7$ & High quality with 3d primitives, direct bitmap drawing (not implemented yet)\\ +% \hline +% $8$ & Draw dots instead of primitives (extremely fast)\\ +% \hline +% \end{tabular} +% \end{center} +% +% \DescribeMacro{\mgltexon} This command has the same effect as the package option |on|, i.e., create all the scripts and corresponding graphics, but its effect is local, meaning that it work only from the point it is used on. +% \begin{center} +% \begin{tabular}{l} +% \hline\\[-0.75em] +% |\mgltexon|\\[0.25em] +% \hline +% \end{tabular} +% \end{center} +% +% \DescribeMacro{\mgltexoff} This command has the same effect as the package option |off|, i.e., DO NOT create the scripts and corresponding graphics, and include images anyway, but its effect is also local, meaning that it work only from the point it is used on. +% \begin{center} +% \begin{tabular}{l} +% \hline\\[-0.75em] +% |\mgltexoff|\\[0.25em] +% \hline +% \end{tabular} +% \end{center} +% +% Observe the commands |\mgltexon| and |\mgltexoff| can be used to save compilation time of a document. For example, when writing an article, if the graphics of the first section are already in final version, instead of compilling them every time \LaTeX{} is called, they can be created only once, and then the section can be wrapped with |mgltexoff| and |mgltexon|, so the graphics do not get recompiled again (wasting time), but only included. +% +% \DescribeMacro{\mglcomments} This command has the same effect as the package option |comments|, i.e., show all the commentaries contained int the |mglcomment| environments, but its effect is local, meaning that it work only from the point it is used on. +% \begin{center} +% \begin{tabular}{l} +% \hline\\[-0.75em] +% |\mglcoments|\\[0.25em] +% \hline +% \end{tabular} +% \end{center} +% \DescribeMacro{\mglnocomments} This command has the same effect as the package option |nocomments|, i.e., DO NOT show the contentsof the |mglcomment| environments, but its effect is also local, meaning that it work only from the point it is used on. +% \begin{center} +% \begin{tabular}{l} +% \hline\\[-0.75em] +% |\mglnocomments|\\[0.25em] +% \hline +% \end{tabular} +% \end{center} +% +% Observe the commands |\mglcomments| and |\mglnocomments| can be used to activate/deactivate commentaries on the document: just like \LaTeX{} commentaries, but with the possibilty of making them visible/invisible. This feature could be used, for example, to show remainders or commentaries for readers of test versions of an article. +% % \DescribeMacro{\mglTeX} This command just pretty-prints the name of the package. % \begin{center} % \begin{tabular}{l} @@ -251,6 +394,38 @@ % \end{tabular} % \end{center} % +% \subsection{User-definable macros} +% \noindent There are two macros that the user is allowed to modify: +% +% \DescribeMacro{\mgltexsignature} +% As an alternative to the |mglsignature| environment for declaring signatures, the user can manually redefine the signature macro |\mgltexsignature|, according to the following rules: +% \begin{itemize} +% \item The positions of the comment signs for the MGL language have to be manually specified in the signature using the |\mglcomm| macro. +% \item The new-line character is declared as ``|^^J|''. +% \item A percent sign (|%|) has to be added at the end of every physical line of |\mgltexsignature|, otherwise an inelegant space at the beginning of every line will appear. +% \item Any \LaTeX{} command can be used in this case. +% \end{itemize} +% For example, the default signature: +% \begin{quote} +% \mglcomm\\ +% \mglcomm\ This script was generated from \meta{document}.mgl on date \meta{today}\\ +% \mglcomm +% \end{quote} +% can be achieved with +% \begin{verbatim} +% \def\mgltexsignature{% +% \mglcomm^^J% +% \mglcomm\ This script was generated from \jobname.mgl on date \today^^J% +% \mglcomm% +% } +% \end{verbatim} +% +% \DescribeMacro{\mglcommonscript} +% It is the name for the common script that takes the contents of the |mglcommon| environment. For example, the default name of the script (``mgl\_common\_script'') is defined by doing +% \begin{verbatim} +% \def\mglcommonscript{mgl_common_script} +% \end{verbatim} +% % \subsection{Behavior of \textsf{\mglTeX}} % \noindent As a convenient feature, the environments |mglcode|, |mglscript| and |mglblock| will automatically check if they are being used to create different scripts with the same name, in which case \textsf{\mglTeX} will issue a warning; however, if one of these environments overwrite an external script (not embedded in the document), it won't be noticed. Likewise, the user will be warned if the environment |mglfunc| is being used to create different MGL functions with the same name. % @@ -263,13 +438,40 @@ % } % \end{center} % Notice that the first time \LaTeX{} is executed, many of these boxes will appear in the document because the graphics from the MGL scripts are created, but not all are included (until \LaTeX{} is run for the second time). -% -% \StopEventually{} +% \section{Warning for the user} +% \mglTeX{} assummes that the |\begin{|\meta{environment}|}| and |\end{|\meta{environment}|}| commands will occupy their own physical line of \LaTeX{} code. So the correct form to use the environments is the following: +% \begin{verbatim} +% \begin{} +% +% \end{} +% \end{verbatim} +% The following forms of use could cause problems: +% \begin{verbatim} +% \begin{}\end{} +% \end{verbatim} +% \begin{verbatim} +% \begin{} +% \end{} +% \end{verbatim} +% \begin{verbatim} +% \begin{} +% +% \end{} +% \end{verbatim} +% One of the reasons for this is that some of the environments in \mglTeX{} are programmed to ignore the empty space following the |\begin{|\meta{environment}|}|, which would cause an inelegant empty line in the script, so the first two incorrect forms would cause \mglTeX{} to ignore a complete line of code. The other reason is the method used to detect the |\end{|\meta{environment}|}| command, which could fail in the case of the third incorrect use. +% \StopEventually{\PrintChanges\PrintIndex} % \section{Implementation} +% \noindent This section documents the implementation of \mglTeX. Its purpose is to facilitate the comprehension and maintenance of the package. +% \subsection{Initialization} +% \noindent The \textsf{keyval} package is loaded to facilitate the declaration of \meta{key}=\meta{value} options for commands and environments; the \textsf{graphicx} package is loaded in order to manipulate and include the images created by MGL code. % \begin{macrocode} \RequirePackage{keyval} \RequirePackage{graphicx} +% \end{macrocode} + +% We declare the options of the package. The first two are |draft| and |final|, which are passed directly to the \textsf{graphicx} package. +% \begin{macrocode} \DeclareOption{draft}{% \PassOptionsToPackage{\CurrentOption}{graphicx}% @@ -277,14 +479,52 @@ \DeclareOption{final}{% \PassOptionsToPackage{\CurrentOption}{graphicx}% } +% \end{macrocode} +% +% The next two options are |on| and |off|, where |on| indicates \mglTeX{} to create every script and every corresponding image every time \LaTeX{} is executed, while |off| tells not to do it, but to include the images anyway. First we declare a flag (boolean variable) |\@mgltex@on@| to know if the used passed the |on| or the |off| option. +% \begin{macrocode} +\newif\if@mgltex@on@ +% \end{macrocode} +% If the user passes the option |on|, |\@mgltex@on@| is true, and the command |\mgl@write| (which takes care of writing code to the scripts) is the normal \LaTeX{} |\immediate\write| commands; +% \changes{v.2.0}{2014/11/15}{Add package options \texttt{on} and \texttt{off}} +% \begin{macrocode} +\DeclareOption{on}{% + \@mgltex@on@true% + \def\mgl@write#1#2{% + \immediate\write#1{#2}% + } +} +% \end{macrocode} +% if the user passes the option |off|, |\@mgltex@on@| is false, and the command |\mgl@write| does nothing (doesn't write to scripts). +% \begin{macrocode} +\DeclareOption{off}{% + \@mgltex@on@false% + \def\mgl@write#1#2{}% +} +% \end{macrocode} +% The next options are |comments| and |nocomments|, where |comments| indicates \mglTeX{} to show the comments included inside |\mglcomments| environments, while |nocomments| tells not to do it. First we create a flag that will indicate which of these options is passed by the user. +% \begin{macrocode} +\newif\if@mgl@comments@ +% \end{macrocode} +% If the user passes the option |comments|, |\@mgl@comments@| is true, and the |\mglcomments| environments print their contents; +% \changes{v2.0}{2014/11/22}{Add package options \texttt{comments} and \texttt{nocomments}} +% \begin{macrocode} +\DeclareOption{comments}{% + \@mgl@comments@true% +} +% \end{macrocode} +% if the user passes the option |nocomments|, |\@mgl@comments@| is false, and the |\mglcomments| environments won't print their contents. +% \begin{macrocode} +\DeclareOption{nocomments}{% + \@mgl@comments@false% +} +% \end{macrocode} +% We then indicate the supported extensions to save the images created by the package, and the corresponding package options. The chosen extension is stored in the |\mgl@image@ext| macro for future use. +% \begin{macrocode} -\DeclareGraphicsExtensions{.png,.eps,.jpg,.jpeg,.bps,.pdf,.epsz,.eps.gz,.bpsz,.bps.gz,.gif} -%\DeclareGraphicsExtensions{.png,.eps,.jpg,.jpeg,.bps,.pdf,.gif} -%\DeclareGraphicsRule{*}{eps}{*}{} -%\DeclareGraphicsRule{.eps.gz}{eps}{.eps.bb}{`gunzip -c #1}% gzipped EPS -%\DeclareGraphicsRule{.epsz}{eps}{.eps.bb}{`gunzip -c #1}% gzipped EPS -%\DeclareGraphicsRule{.bps.gz}{eps}{.bps.bb}{`gunzip -c #1}% gzipped EPS -%\DeclareGraphicsRule{.bpsz}{eps}{.bps.bb}{`gunzip -c #1}% gzipped EPS +\DeclareGraphicsExtensions{% + .png,.eps,.jpg,.jpeg,.bps,.pdf,.epsz,.eps.gz,.bpsz,.bps.gz,.gif% +} \DeclareOption{jpg}{\def\mgl@image@ext{.jpg}} \DeclareOption{jpeg}{\def\mgl@image@ext{.jpeg}} @@ -297,21 +537,22 @@ \DeclareOption{gif}{\def\mgl@image@ext{.gif}} \DeclareOption{tex}{\def\mgl@image@ext{.tex}} -%\DeclareOption{svg}{\def\mgl@image@ext{.svg}} -%\DeclareOption{svgz}{\def\mgl@image@ext{.svgz}} -%\DeclareOption{bmp}{\def\mgl@image@ext{.bmp}} -%\DeclareOption{tga}{\def\mgl@image@ext{.tga}} -%\DeclareOption{mgld}{\def\mgl@image@ext{.mgld}} -%\DeclareOption{json}{\def\mgl@image@ext{.json}} -%\DeclareOption{jsonz}{\def\mgl@image@ext{.jsonz}} -%\DeclareOption{obj}{\def\mgl@image@ext{.obj}} -%\DeclareOption{xyz}{\def\mgl@image@ext{.xyz}} -%\DeclareOption{stl}{\def\mgl@image@ext{.stl}} -%\DeclareOption{off}{\def\mgl@image@ext{.off}} -%\DeclareOption{prc}{\def\mgl@image@ext{.prc}} - -\ExecuteOptions{final,eps} +% \end{macrocode} +% +% Other options produce an error message. +% \begin{macrocode} +\DeclareOption*{\@unknownoptionerror} +% \end{macrocode} +% +% The default options for the package are set to |final| and |eps|, then the options passed by the user are processed. +% \begin{macrocode} + +\ExecuteOptions{final,on,nocomments,eps} \ProcessOptions* +% \end{macrocode} +% +% Declare the \meta{key}=\meta{value} pairs for the |mgl| environment and companions. The pairs corresponding to the |\includegraphics| command are repeated, and saved in the |\graph@keys| macro; the new option is |imgext|, which can be used to overwrite the default extension chosen for the package. Notice that |imgext| can be any supported extension by MathGL but, of course, not all of them are supported by \LaTeX. +% \begin{macrocode} \define@key{mgl@keys}{bb}{\g@addto@macro{\graph@keys}{bb=#1,}} \define@key{mgl@keys}{bbllx}{\g@addto@macro{\graph@keys}{bbllx=#1,}} @@ -337,6 +578,10 @@ \define@key{mgl@keys}{read}{\g@addto@macro{\graph@keys}{read=#1,}} \define@key{mgl@keys}{command}{\g@addto@macro{\graph@keys}{command=#1,}} \define@key{mgl@keys}{imgext}{\def\mgl@image@ext{.#1}} +% \end{macrocode} + +% We do the same for the |\mglplot| command. The options for the |\includegraphics| command are repeated and stored in the |\graph@keys| macro; the new options are |imgext|, which is the same as the one for the |mgl| environment, and |setup|, which is used to specify a keyword associated to a block of MGL code stored by the |mglsetup| environment. +% \begin{macrocode} \define@key{mglplot@keys}{bb}{\g@addto@macro{\graph@keys}{bb=#1,}} \define@key{mglplot@keys}{bbllx}{\g@addto@macro{\graph@keys}{bbllx=#1,}} @@ -361,208 +606,374 @@ \define@key{mglplot@keys}{ext}{\g@addto@macro{\graph@keys}{ext=#1,}} \define@key{mglplot@keys}{read}{\g@addto@macro{\graph@keys}{read=#1,}} \define@key{mglplot@keys}{command}{\g@addto@macro{\graph@keys}{command=#1,}} -\define@key{mglplot@keys}{outext}{\def\mglplot@output@ext{.#1}} -\define@key{mglplot@keys}{settings}{\def\mglplot@settings{#1}} - -\def\mgl@dir{} -\def\mgldir#1{% - \def\mgl@dir{#1}% -} -\@onlypreamble\mgldir - -\newwrite\mgl@script -\AtBeginDocument{% - \immediate\openout\mgl@script="\mgl@dir\jobname.mgl"% -} -\AtEndDocument{% - \immediate\write\mgl@script{}% - \immediate\write\mgl@script{stop}% - \mgl@func% - \immediate\closeout\mgl@script% - \immediate\write18{mglconv -n "\mgl@dir\jobname.mgl"}% -} +\define@key{mglplot@keys}{imgext}{\def\mglplot@image@ext{.#1}} +\define@key{mglplot@keys}{setup}{\def\mglplot@setup{#1}} +% \end{macrocode} -\def\mglplotsettings@defined{} -\newcommand\mglplotsettings[1][generic]{% - \test@mglplotsettings@defined{#1}% - \expandafter\def\csname mgl@setup@#1\endcsname{\immediate\write\mgl@script{}}% - \g@addto@macro{\mglplotsettings@defined}{#1,}% - \let\do\@makeother \dospecials% - \endlinechar`\^^M \catcode`\^^M\active% - \catcode`\ =10% - \expandafter\mglplotsettings@write@line% -} -\def\test@mglplotsettings@defined#1{% - \def\this@setup{#1}% - \@for\mglplotsettings@name:=\mglplotsettings@defined\do{% - \ifx\this@mglplotsettings\mglplotsettings@name% - \PackageWarning{\mgl@name}{Redefining "#1" setup for \noexpand\mglplot}% - \fi% - }% -} -\begingroup% - \catcode`\^^M\active% - \gdef\mglplotsettings@write@line#1^^M{% - \def\next@action{% - \expandafter\g@addto@macro\csname mgl@setup@\this@setup\endcsname{\immediate\write\mgl@script{#1}}% - \mglplotsettings@write@line% - }% - \test@end@mglplotsettings{#1}% - \next@action% - }% -\endgroup -\begingroup% - \escapechar=-1 \relax% - \xdef\end@mglplotsettings{\string\\end\string\{mglplotsettings\string\}}% -\endgroup -\def\test@end@mglplotsettings#1{% - \edef\this@line{#1}% - \ifx\this@line\end@mglplotsettings% - \def\next@action{\end{mglplotsettings}}% - \fi% -} -\def\endmglplotsettings{} +% A special extension for images created with MathGL is ``.tex'', so we store it within a macro for future use. +% \begin{macrocode} \def\TeX@ext{.tex} -\newcounter{mgl@image@no} - -\def\mglplot{% - \@ifnextchar[{\@mglplot}{\@mglplot[]}% -} -\def\@mglplot[#1]{% - \def\mglplot@settings{generic}% - \def\graph@keys{}% - \setkeys{mglplot@keys}{#1}% - \stepcounter{mgl@image@no}% - \ifx\csname mgl@setup@\mglplot@settings\endcsname\@undefined% - \PackageError{\mgl@name}{Setup "\mglplot@settings" undefined}{}% - \else% - \csname mgl@setup@\mglplot@settings\endcsname% - \fi% - \@@mglplot% -} -\long\def\@@mglplot#1{% - \immediate\write\mgl@script{\detokenize{#1}}% - \immediate\write\mgl@script{write '\mgl@dir\jobname-mgl-\arabic{mgl@image@no}\mgl@image@ext'}% - \immediate\write\mgl@script{reset}% - \mgl@include@image{\mgl@dir\jobname-mgl-\arabic{mgl@image@no}}% -} - -\newcommand\mgl[1][]{% - \def\graph@keys{}% - \setkeys{mgl@keys}{#1}% - \let\do\@makeother \dospecials% - \endlinechar`\^^M \catcode`\^^M\active% - \catcode`\ =10% - \mgl@write@line% -} -\begingroup% - \escapechar=-1 \relax% - \xdef\end@mgl{\string\\end\string\{mgl\string\}}% -\endgroup -\begingroup% - \catcode`\^^M\active% - \gdef\mgl@write@line#1^^M{% - \def\next@action{% - \immediate\write\mgl@script{#1}% - \mgl@write@line% - }% - \test@end@mgl{#1}% - \next@action% - }% -\endgroup -\def\test@end@mgl#1{% - \edef\this@line{#1}% - \ifx\this@line\end@mgl% - \def\next@action{\end{mgl}}% - \fi% -} -\def\endmgl{% - \stepcounter{mgl@image@no}% - \immediate\write\mgl@script{write '\mgl@dir\jobname-mgl-\arabic{mgl@image@no}\mgl@image@ext'}% - \immediate\write\mgl@script{reset}% - \mgl@include@image{\mgl@dir\jobname-mgl-\arabic{mgl@image@no}}% -} +% \end{macrocode} +% \subsection{Environments for MGL code embedding} +% \begin{macro}{\mgl@include@image} +% This is the command that will include graphics created by MGL code. We can't use |\includegraphics| directly for two reasons: first, MathGL has the capacity of creating graphics with \LaTeX{} commands (with the aid of the \textsf{tikz} package), in which case there is no image, but a ``.tex'' file, which has to be included; the second reason is that |\includegraphics| issues an error when the specified image doesn't exist, and remember that the first \LaTeX{} run only creates the images at the end of the document, but they cannot be included yet, so there would be a lot of errors in the process of compilation. +% \begin{macrocode} \def\mgl@include@image#1{% +% \end{macrocode} +% If the extension of the graphics is ``.tex'', +% \begin{macrocode} \ifx\mgl@image@ext\TeX@ext% +% \end{macrocode} +% first check if the file exists; +% \begin{macrocode} \IfFileExists{#1.tex}{% +% \end{macrocode} +% if so, include it, +% \begin{macrocode} \include{#1}% }{% +% \end{macrocode} +% otherwise use the command |\mgl@img@not@found| to create a warning. +% \begin{macrocode} \mgl@img@not@found{#1}% }% +% \end{macrocode} +% If the extension of the graphics is not ``.tex'', +% \begin{macrocode} \else% +% \end{macrocode} +% we define the next action to be performed as warning that requested image doesn't exist. This is stored in the |\next@action| macro, and will be overwriten if the image is found. +% \begin{macrocode} \def\next@action{\mgl@img@not@found{#1}}% +% \end{macrocode} +% For every extension supported by \mglTeX{}, +% \begin{macrocode} \@for\img@ext:=\Gin@extensions\do{% +% \end{macrocode} +% if the file with the current extension exists, +% \begin{macrocode} \IfFileExists{#1\img@ext}{% +% \end{macrocode} +% overwrite the |\next@action| macro so it uses the |\includegraphics| command to include the image, otherwise do nothing. +% \begin{macrocode} \def\next@action{% \expandafter\includegraphics\expandafter[\graph@keys]{#1}% }% }{}% }% +% \end{macrocode} +% Execute |\next@action|. +% \begin{macrocode} \next@action% \fi% } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mgl@img@not@found} +% \changes{v2.0}{2014/11/22}{Fixed incompatibility of command \texttt{\textbackslash{}mgl@img@not@found} with environment \texttt{tabular}} +% When this command is called with the name of a MGL image as argument, it issues a package warning indicating that the MGL image can't be found, and creates the following box in the corresponding position: +% \begin{center} +% \framebox[10em]{% +% \centering% +% \bfseries\Huge% +% \vbox{MGL\\image\\not\\found}% +% }% +% \end{center} +% \begin{macrocode} \def\mgl@img@not@found#1{% - \PackageWarning{\mgl@name}{MGL image "#1" not found}% + \PackageWarning{mgltex}{MGL image "#1" not found}% \framebox[10em]{% \centering% \bfseries\Huge% - \vbox{MGL\\image\\not\\found}% + \begin{tabular}{c}MGL\\image\\not\\found\end{tabular}% }% } +% \end{macrocode} +% \end{macro} +% \begin{environment}{mgl} +% This environment writes its contents to the main script \meta{document}.mgl. +% +% First, declare a counter for numeration and naming of the images created from the main script \meta{document}.mgl. +% \begin{macrocode} -\bgroup% - \escapechar=-1\relax% - \xdef\end@mgladdon{\string\\end\string\{mgladdon\string\}}% -\egroup% -\newenvironment{mgladdon}{% - \def\test@end@mgl##1{% - \edef\this@line{##1}% - \ifx\this@line\end@mgladdon% - \def\next@action{\end{mgladdon}}% - \fi% - }% - \mgl[]% -}{} - -\def\mgl@script@written{} +\newcounter{mgl@image@no} +% \end{macrocode} +% Create an output stream for the main script \meta{document}.mgl. +% \begin{macrocode} + +\newwrite\mgl@script +% \end{macrocode} +% Open the main script at the beginning of the document (at the moment of the |\begin{document}| command). +% \begin{macrocode} +\AtBeginDocument{% + \if@mgltex@on@% + \immediate\openout\mgl@script="\mgl@dir\jobname.mgl"% + \mglsignature@write\mgl@script% + \fi% +} +% \end{macrocode} +% At the end of the document (at the moment of the |\end{document}| command): +% \begin{macrocode} +\AtEndDocument{% +% \end{macrocode} +% write an empty line on the main script (just for elegance), +% \begin{macrocode} + \mgl@write\mgl@script{}% +% \end{macrocode} +% write the MGL \emph{stop} command to stop the MathGL compiler. +% \begin{macrocode} + \mgl@write\mgl@script{stop}% +% \end{macrocode} +% The |\mgl@func| is a buffer that contains instructions to write MGL functions declared with |mglfunc| environment. Here, we execute those instructions. +% \begin{macrocode} + \mgl@func% +% \end{macrocode} +% Close the main script. +% \begin{macrocode} + \immediate\closeout\mgl@script% +% \end{macrocode} +% Use the program |mglconv| (part of MathGL) to compile the main script. +% \begin{macrocode} + \mgl@write{18}{mglconv -n "\mgl@dir\jobname.mgl"}% +} + +% \end{macrocode} +% \begin{macro}{\mgl} +% The beginning of the |mgl| environment. +% \begin{macrocode} + +\newcommand\mgl[1][]{% +% \end{macrocode} +% First, process the \meta{key}=\meta{value} options for the environment. +% \begin{macrocode} + \def\graph@keys{}% + \setkeys{mgl@keys}{#1}% +% \end{macrocode} +% Now, make every ``special'' character (\textbackslash, \$, etc.) of category $13$ (other), i.e., make them common characters. +% \begin{macrocode} + \let\do\@makeother \dospecials% +% \end{macrocode} +% Add an end-line character at the end of every read line. This end-line character is declared active (category 12). +% \begin{macrocode} + \endlinechar`\^^M \catcode`\^^M\active% +% \end{macrocode} +% Spaces characters are category 10; the spaces at the beginning of every read line are ignored. +% \begin{macrocode} + \catcode`\ =10% +% \end{macrocode} +% Finally, the command that reads/writes each line of the contents of the environment is called. +% \begin{macrocode} + \mgl@write\mgl@script{quality \mgl@quality}% + \expandafter\mgl@write@line% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\end@mgl} +% Define a macro that contains the |\end{mgl}| command as text, so the end of the environment can be tested by comparison with it. From now on, we adopt the convention that the macro |\end@|\meta{environment} contains the |\end{|\meta{environment}|}| command as text. +% \begin{macrocode} +\begingroup% + \escapechar=-1 \relax% + \xdef\end@mgl{\string\\end\string\{mgl\string\}}% +\endgroup +% \end{macrocode} +% \end{macro} + +% \begin{macro}{\mgl@write@line} +% This command reads each line from the |mgl| environment and writes it to the general script \meta{document}.mgl. We start by wrapping the new command with a \LaTeX{} group because we will change the code of the end-line character to ``active'' \emph{locally}, so we can indicate |\mgl@write@line| that its argument stretches until the end of the line. +% \begin{macrocode} +\begingroup% +% \end{macrocode} + +% Declare the end-line character as active. +% \begin{macrocode} + \catcode`\^^M\active% +% \end{macrocode} +% The command |\mgl@write@line| reads its argument until it finds the end-line character, i.e., it reads a complete line of text, which is MGL code in this case. +% \begin{macrocode} + \gdef\mgl@write@line#1^^M{% +% \end{macrocode} +% The next action to be performed is write the read line of code to the main script \meta{document}.mgl and recursively call |\mgl@write@line|, so it reads the next line of text. These instructions are stored in the |\next@action| macro. +% \begin{macrocode} + \def\next@action{% + \mgl@write\mgl@script{#1}% + \mgl@write@line% + }% +% \end{macrocode} +% The |\test@end@mgl| command test if the end of the |mgl| environment has been reached in the current line. If so, it overwrites the |\next@action| macro so it doesn't read the next line of text, but executes the |\end{mgl}| command (see bellow). +% \begin{macrocode} + \test@end@mgl{#1}% +% \end{macrocode} +% Execute the |\next@action| macro. +% \begin{macrocode} + \next@action% + }% +\endgroup +% \end{macrocode} +% \end{macro} + +% \begin{macro}{\test@end@mgl} +% This command checks if its argument is equal to |\end@mgl|; if so, overwrites the |\next@action| macro (see above) so that it executes the end of the |mgl| environment (|\end{mgl}|). Here, we adopt another convention: the |\test@end@|\meta{environment} checks if its argument is equal to |\end@|\meta{environment}, i.e., tests whether the |\end{|\meta{environment}|}| command has been reached, in which case, it executes that command. +% \begin{macrocode} +\def\test@end@mgl#1{% + \edef\this@line{#1}% + \ifx\this@line\end@mgl% + \def\next@action{\end{mgl}}% + \fi% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\endmgl} +% The end of the environment is quite simple: the |mgl@image@no| counter is increased by one, then the MGL command to save the corresponding image is written; the name given to the image is ``\meta{document}-mgl-\meta{mgl@image@no}.\meta{mgl@image@ext}''; the MGL \emph{reset} command is written in the main script to clean the image and restart graphic parameters for the following image to be created. Finally, the |\mgl@include@image| command (see below) is called to include the image created. +% \begin{macrocode} +\def\endmgl{% + \stepcounter{mgl@image@no}% + \mgl@write\mgl@script{% + write '\mgl@dir\jobname-mgl-\arabic{mgl@image@no}\mgl@image@ext'% + }% + \mgl@write\mgl@script{reset}% + \mgl@write\mgl@script{}% + \mgl@include@image{\mgl@dir\jobname-mgl-\arabic{mgl@image@no}}% +} +% \end{macrocode} +% \end{macro} +% \end{environment} +% \begin{environment}{mgladdon} +% This is just a modification of the |mgl| environment. First, we define the |\end@mgladdon| to contain the |\end{mgladdon}| command as text as specified above, then we redefined |\test@end@mgl| command to check for the end of the |mgladdon| environment instead of |mgl|, finally we call the |\mgl| command with no options. The end of |mgladdon| is defined to do nothing. +% \begin{macrocode} + +\bgroup% + \escapechar=-1\relax% + \xdef\end@mgladdon{\string\\end\string\{mgladdon\string\}}% +\egroup% +\newenvironment{mgladdon}{% + \def\test@end@mgl##1{% + \edef\this@line{##1}% + \ifx\this@line\end@mgladdon% + \def\next@action{\end{mgladdon}}% + \fi% + }% + \mgl[]% +}{} +% \end{macrocode} +% \end{environment} +% \begin{environment}{mglcode} +% This is like |mgl|, but it writes its contents to its own file, whose name is passed as mandatory argument. +% \begin{macro}{\mgl@script@written} + +% The names of all the scripts written from the \LaTeX{} document will be stored in this macro, so we can later check if some script is being overwritten. This macro will be used in other environments. +% \begin{macrocode} +\def\mgl@script@written{} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mgl@out@stream} +% Declare an output stream for MGL scripts other than the main one. This stream will be used in other environments. +% \begin{macrocode} \newwrite\mgl@out@stream +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglcode} +% The beginning of the |mglcode| environment. +% \begin{macrocode} \newcommand\mglcode[2][]{% \def\graph@keys{}% +% \end{macrocode} +% Process the \meta{key}=\meta{value} options. These are the same for the |mgl| environment. +% \begin{macrocode} \setkeys{mgl@keys}{#1}% +% \end{macrocode} +% Test if a script with the same name is already created from the \LaTeX{} document. If so, a warning is issue, but we proceed anyway. +% \begin{macrocode} \test@mgl@script@written{#2}% +% \end{macrocode} +% Add the script's name to the |\mgl@script@written| macro. +% \begin{macrocode} \xdef\mgl@script@written{\mgl@script@written#2,}% +% \end{macrocode} +% Open the script for writing. +% \begin{macrocode} \def\this@script{#2}% - \immediate\openout\mgl@out@stream=\mgl@dir\this@script.mgl% + \if@mgltex@on@% + \immediate\openout\mgl@out@stream=\mgl@dir\this@script.mgl% + \mglsignature@write\mgl@out@stream% + \fi% +% \end{macrocode} +% Here, we do the same changes of categories as in the |mgl| environment, except for the spaces, which in this case will be respected, even the ones at the beginning of each like, i.e., we will write each line \emph{verbatim}. +% \begin{macrocode} \let\do\@makeother \dospecials% \endlinechar`\^^M \catcode`\^^M\active% \obeyspaces% - \mglcode@write@line% +% \end{macrocode} +% Call the command that will write each line of the contents of the environment. +% \begin{macrocode} + \expandafter\mglcode@write@line% } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\test@mgl@script@written} +% The macro that checks is we are overwriting any script. +% \begin{macrocode} \def\test@mgl@script@written#1{% +% \end{macrocode} +% For every script already written (whose name is stored in |\mgl@script@written|), check if the current script's name matches; if so, issue a warning telling we are overwriting, but proceed. +% \begin{macrocode} \edef\this@script{#1}% \@for\mgl@script@name:=\mgl@script@written\do{% \ifx\this@script\mgl@script@name% - \PackageWarning{\mgl@name}{Overwriting MGL script "\this@script.mgl"}% + \PackageWarning{mgltex}{Overwriting MGL script "\this@script.mgl"}% \fi% }% } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglcode@write@line} +% This writes each line of the contents of the |mglcode| environment. However, contrary to the case of the |\mgl@write@line| command, it doesn't read line by line, but character by character, and stores each word in |\mgl@word| and each line in |\mgl@line|. +% \begin{macrocode} +\newtoks\mgl@word +\newtoks\mgl@line \def\mglcode@write@line#1{% +% \end{macrocode} +% The next action (stored as |\next@action|) is to read the following character, unless overwritten later. +% \begin{macrocode} \let\next@action\mglcode@write@line% +% \end{macrocode} +% If the current character is an end-line character, +% \begin{macrocode} \expandafter\if#1\^^M% - \immediate\write\mgl@out@stream{\the\mgl@line}% - \mgl@line{}% +% \end{macrocode} +% write the contents of |\mgl@line|, i.e., the current line, and clean |\mgl@word| and |\mgl@line|; +% \begin{macrocode} + \mgl@write\mgl@out@stream{\the\mgl@line}% \mgl@word{}% + \mgl@line{}% +% \end{macrocode} +% if the current character is a space, clean |\mgl@word|, but add the space to |\mgl@line|; +% \begin{macrocode} \else\expandafter\if#1\space% \mgl@word{}% \mgl@line\expandafter{\the\mgl@line#1}% +% \end{macrocode} +% otherwise, the current character is alphanumeric and is added both to |\mgl@word| and |\mgl@line|, and +% \begin{macrocode} \else% \mgl@word\expandafter{\the\mgl@word#1}% \mgl@line\expandafter{\the\mgl@line#1}% +% \end{macrocode} +% we test if the current word (|\mgl@word|) is |\end{mglcode}|, in which case, |\next@action| is overwritten to |\end{mglcode}|. +% \begin{macrocode} \test@end@mglcode{\the\mgl@word}% \fi\fi% +% \end{macrocode} +% Finally, execute |\next@action|. +% \begin{macrocode} \next@action% } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\test@end@mglcode} +% The |\test@end@mglcode| checks if it's argument is equal to |\end@mglcode|, in which case overwrites |\next@action| to |\end{mglcode}|. +% \begin{macrocode} \begingroup% \escapechar=-1\relax% \xdef\end@mglcode{\string\\end\string\{mglcode\string\}}% @@ -573,11 +984,26 @@ \def\next@action{\end{mglcode}}% \fi% } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\endmglcode} +% The end of the |mglcode| environment. It closes the output stream |\mgl@out@stream|, and calls the \textsf{mglconv} program (part of MathGL) to execute the script. Finally, the |\mgl@include@image| command is used to include the image created. +% \begin{macrocode} \def\endmglcode{% \immediate\closeout\mgl@out@stream% - \immediate\write18{mglconv "\mgl@dir\this@script.mgl" -o "\mgl@dir\this@script\mgl@image@ext"}% + \mgl@write{18}{% + mglconv "\mgl@dir\this@script.mgl" -s "\mgl@dir\mglcommonscript.mgl" -o "\mgl@dir\this@script\mgl@image@ext"% + }% \mgl@include@image{\mgl@dir\this@script}% } +% \end{macrocode} +% \end{macro} +% \end{environment} +% +% \begin{environment}{mglscript} +% This is just a modification of the |mglcode| environment. First, we define the |\end@mglscript| macro; then we modify the |\test@end@mglcode| to check for |\end{mglscript}| instead of |\end{mglcode}|; finally, we call the |\mglcode| macro with the same mandatory argument as |mglscript|. The |\end{mglscript}| just closes the output stream |\mgl@out@stream|, but doesn't create nor includes any image. +% \begin{macrocode} \bgroup% \escapechar=-1\relax% @@ -594,19 +1020,61 @@ }{% \immediate\closeout\mgl@out@stream% } +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{mglfunc} +% This environment is used to create MGL functions in the main script \meta{document}.mgl. +% \begin{macro}{\mglfunc@defined} +% Within this macro we will store the names of the MGL functions already defined from the \LaTeX{} document, so that we can check if we are overwriting one of them +% \begin{macrocode} \def\mglfunc@defined{} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mgl@func} +% This is a buffer to store the instructions to write the MGL functions code when the |\end{document}| command is called. This is done this way, because the functions have to be after the \emph{stop} command from the MGL language, which stops the execution of the MGL compiler, so no code should be after the \emph{stop}, except for functions. +% \begin{macrocode} \def\mgl@func{} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglgunc} +% The beginning of the |mglfunc| environment. +% \begin{macrocode} + \newcommand\mglfunc[2][0]{% +% \end{macrocode} +% First, check if a function with the current name is already defined, in which case we issue a warning, but proceed anyway. +% \begin{macrocode} \test@mglfunc@defined{#2}% +% \end{macrocode} +% Add the name of the current function to the list of functions defined. +% \begin{macrocode} \g@addto@macro{\mglfunc@defined}{#2,}% +% \end{macrocode} +% \end{macro} +% Here we do the same changes of categories as in the |mgl| environment. +% \begin{macrocode} \let\do\@makeother \dospecials% \endlinechar`\^^M \catcode`\^^M\active% \catcode`\ =10% - \g@addto@macro{\mgl@func}{\immediate\write\mgl@script{}}% - \g@addto@macro{\mgl@func}{\immediate\write\mgl@script{func '#2' #1}}% - \expandafter\mglfunc@ignore@line% +% \end{macrocode} +% Write an empty line in the main script just for elegance (and to visually separate different functions, too). +% \begin{macrocode} + \g@addto@macro{\mgl@func}{\mgl@write\mgl@script{}}% +% \end{macrocode} +% Write the heading of the function. +% \begin{macrocode} + \g@addto@macro{\mgl@func}{\mgl@write\mgl@script{func '#2' #1}}% +% \end{macrocode} +% Call the command that will write each line of the contents of the environment. +% \begin{macrocode} + \expandafter\mglfunc@write@line% } +% \end{macrocode} +% \begin{macro}{\test@mglfunc@defined} +% This command tests if a function with a given name---given as argument---is already defined from the \LaTeX{} document; if so, a warning will be issued indicating multiple definitions for the same function, but we will proceed anyway. +% \begin{macrocode} \def\test@mglfunc@defined#1{% \def\this@func{#1}% \@for\mglfunc@name:=\mglfunc@defined\do{% @@ -615,20 +1083,42 @@ \fi% }% } +% \end{macrocode} +% \end{macro} +% We declare \emph{locally} the end-line character as active. +% \begin{macrocode} \begingroup% \catcode`\^^M\active% - \gdef\mglfunc@ignore@line#1^^M{% - \expandafter\mglfunc@write@line% - } +% \end{macrocode} +% \begin{macro}{\mglfunc@write@line} +% This is the command that reads each line of code of the |mglfunc| environment, and stores in the buffer |\mgl@func| the instructions to write each of these lines. +% \begin{macrocode} \gdef\mglfunc@write@line#1^^M{% +% \end{macrocode} +% The next action (|\next@action|) is to store in the buffer the instruction to write the current line, and then call recursively the |\mglfunc@write@line| command, unless overwritten below. +% \begin{macrocode} \def\next@action{% - \g@addto@macro{\mgl@func}{\immediate\write\mgl@script{#1}}% - \mglfunc@write@line% + \g@addto@macro{\mgl@func}{\mgl@write\mgl@script{#1}}% + \expandafter\mglfunc@write@line% }% +% \end{macrocode} +% Check for the end of the |mglfunc| environment, in which case, |\next@action| is redefined to be |\end{mglfunc}|. +% \begin{macrocode} \test@end@mglfunc{#1}% +% \end{macrocode} +% Execute |\next@action|. +% \begin{macrocode} \next@action% }% +% \end{macrocode} +% \end{macro} +% \begin{macrocode} \endgroup +% \end{macrocode} +% \begin{macro}{\end@mglfunc} +% \begin{macro}{\test@end@mglfunc} +% By now, we already know now these two commands work. +% \begin{macrocode} \begingroup% \escapechar=-1 \relax% \xdef\end@mglfunc{\string\\end\string\{mglfunc\string\}}% @@ -639,110 +1129,438 @@ \def\next@action{\end{mglfunc}}% \fi% } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\endmglfunc} +% Just stores in the buffer the instruction that closes the MGL function with the \emph{return} command. +% \begin{macrocode} \def\endmglfunc{% - \g@addto@macro{\mgl@func}{\immediate\write\mgl@script{return}}% + \g@addto@macro{\mgl@func}{\mgl@write\mgl@script{return}}% } -\def\mglblock#1{% - \test@mgl@script@written{#1}% - \xdef\mgl@script@written{\mgl@script@written#1,}% - \def\this@script{#1}% +% \begin{environment}{mglcommon} +% Writes its contents to a common script that will be executed together with each of the other scripts. It is useful to define constants ---for example--- that will be available to all other scripts. +% \begin{macro}{\mglcommonscript} +% \changes{v2.0}{2014/11/22}{Add \texttt{\backslash{}mglcommonscript} user-definable macro} +% We define a macro to store the name of the setup script that will contain common code to all other scripts. The default name is \emph{common\_script}.mgl. +% \begin{macrocode} + +\def\mglcommonscript{mgl_common_script} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\end@mglcommon} +% We already know the purpose of this macro. +% \begin{macrocode} +\bgroup% + \escapechar=-1\relax% + \xdef\end@mglcommon{\string\\end\string\{mglcommon\string\}}% +\egroup% +% \end{macrocode} +% \end{macro} +% +% The |mglcommon| environment redefines the |\test@end@mglcode| so it detects the |\end{mglcommon}| command instead, and uses the |\mglcode| to create the common script. +% \begin{macrocode} +\newenvironment{mglcommon}{% + \def\test@end@mglcode##1{% + \edef\this@word{##1}% + \ifx\this@word\end@mglcommon% + \def\next@action{\end{mglcommon}}% + \fi% + }% + \mglcode{\mglcommonscript}% +}{% + \mgl@write\mgl@out@stream{quality \mgl@quality}% + \immediate\closeout\mgl@out@stream% +} +% \end{macrocode} +% This environment can be used only in the preamble. +% \begin{macrocode} +\@onlypreamble\mglcommon +% \end{macrocode} +% \end{environment} +% \begin{environment}{mglsignature} +% This environment is used to declare signature text that will be written as comment on every script generated by \mglTeX. +% \begin{macro}{\mglcomm} +% We store the comment sign for MGL in this macro. For that, we need to declare \emph{locally} the symbol ``\#'' as one of category $12$. +% \begin{macrocode} +\bgroup + \catcode`#=12 + \gdef\mglcomm{#} +\egroup +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mgltexsignature} +% \changes{v2.0}{2014/11/22}{Add \texttt{\textbackslash{}mgltexsignature} user-definable macro} +% The buffer where the signature will be stored. Here, we declare a default signature. +% \begin{macrocode} +\def\mgltexsignature{% + \mglcomm^^J% + \mglcomm\space This file was autogenerated from the document \jobname.tex on date \today^^J% + \mglcomm% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglsignature} +% The beginning of the |mglsignature| environment. +% \begin{macrocode} +\newcommand\mglsignature{% +% \end{macrocode} +% Delete |\mgltexsignature| contents. +% \begin{macrocode} + \def\mgltexsignature{}% +% \end{macrocode} +% We do the same changes of category as in the |mglcode| environment. +% \begin{macrocode} \let\do\@makeother \dospecials% \endlinechar`\^^M \catcode`\^^M\active% - \obeyspaces% - \immediate\openout\mgl@out@stream="\mgl@dir\this@script.mgl"% - \mglblock@ignore@line% -} -\def\mglblock@ignore@line#1{% - \mglblock@write@line% -} -\def\mglblock@write@line#1{% - \let\next@action\mglblock@write@line% - \expandafter\if#1\^^M% - \immediate\write\mgl@out@stream{\the\mgl@line}% - \mgl@line{}% - \mgl@word{}% - \else\expandafter\if#1\space% - \mgl@word{}% - \mgl@line\expandafter{\the\mgl@line#1}% - \else% - \mgl@word\expandafter{\the\mgl@word#1}% - \mgl@line\expandafter{\the\mgl@line#1}% - \test@end@mglblock{\the\mgl@word}% - \fi\fi% - \next@action% + \@vobeyspaces% +% \end{macrocode} +% Call the command that will store each line of the signature in the |\mgltexsignature| macro. +% \begin{macrocode} + \expandafter\mglsignature@write@line% } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\end@mglsignature} +% We already know the purpose of this command. +% \begin{macrocode} \begingroup% - \escapechar=-1\relax% - \xdef\end@mglblock{\string\\end\string\{mglblock\string\}}% -\endgroup% -\def\test@end@mglblock#1{% - \edef\this@word{#1}% - \ifx\this@word\end@mglblock% - \def\next@action{\end{mglblock}}% + \escapechar=-1 \relax% + \xdef\end@mglsignature{\string\\end\string\{mglsignature\string\}}% +\endgroup +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglsignature@write@line} +% This command stores each line of the signature in the |\mgltexsignature| buffer. +% \begin{macrocode} +\begingroup% +% \catcode`\\=0% + \catcode`\^^M\active% + \gdef\mglsignature@write@line#1^^M{% +% \end{macrocode} +% Unless overwritten later, the next action (|\next@action|) is to store the current line of the signature in the |\mgltexsignature| buffer, ending with a new-line character, and call |\mglsignature@write@line| recursively. +% \begin{macrocode} + \def\next@action{% + \g@addto@macro{\mgltexsignature}{\mglcomm\space#1^^J} + \mglsignature@write@line% + }% +% \end{macrocode} +% We check if the current line is |\end{mglsignature}|, in which case, overwrite |\next@action| to that command. +% \begin{macrocode} + \test@end@mglsignature{#1}% +% \end{macrocode} +% Execute |\next@action|. +% \begin{macrocode} + \next@action% + }% +\endgroup +% \end{macrocode} +% \end{macro} +% \begin{macro}{\test@end@mglsignature} +% We already know the purpose of this command. +% \begin{macrocode} +\def\test@end@mglsignature#1{% + \edef\this@line{#1}% + \ifx\this@line\end@mglsignature% + \def\next@action{\end{mglsignature}}% \fi% } -\newread\mgl@in@stream -\def\endmglblock{% - \immediate\closeout\mgl@out@stream% - \immediate\openin\mgl@in@stream="\mgl@dir\this@script.mgl"% - \begingroup% - \list{\itshape\footnotesize\arabic{mgl@verb@line@no}.}{}% - \setlength{\labelsep}{1em}% - \itemsep\z@skip% - \leftskip\z@skip\rightskip\z@skip% - \verbatim@font% - \parindent\z@\parfillskip\@flushglue\parskip\z@skip% +% \end{macrocode} +% \end{macro} +% \begin{macro}{\endmglsignature} +% The end of the |mglsignature| environment. It just adds a comment sign to |\mgltexsignature| for elegance. +% \begin{macrocode} +\def\endmglsignature{% + \g@addto@macro{\mgltexsignature}{\mglcomm} +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglsignature@write} +% It takes care of writing the signature to the output stream which is passed as its argument. +% \begin{macrocode} +\def\mglsignature@write#1{\mgl@write#1{\mgltexsignature}} +% \end{macrocode} +% \end{macro} +% \end{environment} +% \begin{environment}{mglcomment} +% \changes{v2.0}{2014/11/22}{Add the |mglcomment| environment.} +% An environment to contain multiline comments that won't be printed to the document nor to any script in the case of the user passes the option |nocomments| to the package, and it'll print the comments if the |comments| option is passed to the package. +% +% \begin{macro}{\mglcomment} +% The beginning of the |mglcomment| environment. Here, we change categories of special characters (like \#, \@, etc.) and indicate to obey lines and spaces. +% \begin{macrocode} + +\def\mglcomment{% + \let\do\@makeother\dospecials% + \obeylines% \@vobeyspaces% - \mglblock@read@line% + \verbatim@font% + \small% +% \end{macrocode} +% Call the command that will ignore all the commentary. +% \begin{macrocode} + \mgl@comment% } -\def\mglblock@read@line{% - \stepcounter{mgl@verb@line@no}% - \read\mgl@in@stream to \this@line% - \ifeof\mgl@in@stream% +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mgl@comment} +% This command reads everything up to the |\end{mglcomment}| and ignores it if the |nocomments| option is passed to the package, or prints it otherwise. (We use the trick to consider everything up to the |\end{mglcomment}| the argument of |\mgl@comment|.) +% \begin{macrocode} +\begingroup% +% \end{macrocode} +% We do some adequate changes of code locally, so that \texttt{\textbackslash}, \texttt{\{} and \texttt{\}} are special, and \texttt{\textbar}, \texttt{[} and \texttt{]} take their functions, respectively. +% \begin{macrocode} + \catcode`|=0\catcode`[= 1\catcode`]=2\catcode`\{=12\catcode`\}=12\catcode`\\=12% +% \end{macrocode} +% Define |\mgl@comment| to do nothing with its argument if the |nocomments| option has been passed to the package; otherwise, if the |comments| options has been passed, it will print the commentary, with delimiters to indicate where it starts and where it ends. Then call the end of the environment. +% \begin{macrocode} + |gdef|mgl@comment#1\end{mglcomment}[% + |if@mgl@comments@% + |begin[center]% + <------------------ MGL comment ------------------>% + #1% + <------------------ MGL comment ------------------>% + |end[center]% + |fi% + |end[mglcomment]]% +|endgroup% +% \end{macrocode} +% \end{macro} +% \begin{macro}{\endmglcomment} +% The end of the environment; it does nothing. +% \begin{macrocode} +\def\endmglcomment{} +% \end{macrocode} +% \end{macro} +% \end{environment} + +% \subsection{Fast creation of graphics} +% \begin{environment}{mglsetup} +% This environment is used to store lines of code that need to be repeated many times. Later, the |\mglplot| command (see below) uses this lines of code without the need to repeat them. +% \begin{macro}{\mglsetup@defined} +% A macro to list the names of all the setups already defined. +% \begin{macrocode} + +\def\mglsetup@defined{} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglsetup} +% The beginning of the |mglsetup| environment. It accepts one optional argument, which is a name (keyword) to be associated to the block of code. +% \begin{macrocode} +\newcommand\mglsetup[1][generic]{% +% \end{macrocode} +% Test if there already exists a setup with the current name; if so, issue a warning of redefinition of the setup, but proceed anyway. +% \begin{macrocode} + \test@mglsetup@defined{#1}% +% \end{macrocode} +% Add the name of the current setup to |\mglsetup@defined|. +% \begin{macrocode} + \g@addto@macro{\mglsetup@defined}{#1,}% +% \end{macrocode} +% Define a new buffer which will contain the instructions to write the contents of the environment when the |\mglplot|. command is used. If the |mglsetup| environment is called like |\mglsetup\oarg{\meta{keyword}}|, the buffer will be called |\mgl@setup@\meta{keyword}|; if no name is given, use ``generic'' as keyword. +% \begin{macrocode} + \expandafter\def\csname mgl@setup@#1\endcsname{\mgl@write\mgl@script{}}% + \expandafter\def\csname mgl@setup@#1\endcsname{\mgl@write\mgl@script{quality \mgl@quality}}% +% \end{macrocode} +% Here, we do the same changes of category for special characters as we did in the |mgl| environment. +% \begin{macrocode} + \let\do\@makeother \dospecials% + \endlinechar`\^^M \catcode`\^^M\active% + \catcode`\ =10% +% \end{macrocode} +% Call the command that will store in the buffer the instructions to write the lines of MGL code. +% \begin{macrocode} + \expandafter\mglsetup@write@line% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\test@mglsetup@defined} +% For every name stored in |\mglsetup@defined|, check if its argument (the name of the current setup) matches, in which case we will issue a warning, but proceed. +% \begin{macrocode} +\def\test@mglsetup@defined#1{% + \def\this@setup{#1}% + \@for\mglsetup@name:=\mglsetup@defined\do{% + \ifx\this@mglsetup\mglsetup@name% + \PackageWarning{\mgl@name}{Redefining "#1" setup for \noexpand\mglplot}% + \fi% + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglsetup@write@line} +% This works exactly as the |\mgl@write@line|, but instead of writing directly to a script, it stores the writing instructions in the buffer. +% \begin{macrocode} +\begingroup% + \catcode`\^^M\active% + \gdef\mglsetup@write@line#1^^M{% \def\next@action{% - \immediate\closein\mgl@in@stream% - \endlist% - \endgroup% + \expandafter\g@addto@macro\csname mgl@setup@\this@setup\endcsname{% + \mgl@write\mgl@script{#1}% + }% + \expandafter\mglsetup@write@line% }% + \test@end@mglsetup{#1}% + \next@action% + }% +\endgroup +% \end{macrocode} +% \end{macro} +% \begin{macro}{\end@mglsetup} +% \begin{macro}{\test@end@mglsetup} +% We already know how these two macros work +% \begin{macrocode} +\begingroup% + \escapechar=-1 \relax% + \xdef\end@mglsetup{\string\\end\string\{mglsetup\string\}}% +\endgroup +\def\test@end@mglsetup#1{% + \edef\this@line{#1}% + \ifx\this@line\end@mglsetup% + \def\next@action{\end{mglsetup}}% + \fi% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\endmglsetup} +% The end of the |mglsetup| environment. It does nothing. +% \begin{macrocode} +\def\endmglsetup{} +% \end{macrocode} +% \end{macro} +% \end{environment} + +% \begin{macro}{\mglplot} +% This macro uses the blocks of code stored by |mglsetup| environments to complete the code contained in its mandatory argument. +% +% If there is an optional argument, make |\@mglplot| process it, otherwise pass no argument to |\@mglplot|. +% \begin{macrocode} + +\def\mglplot{% + \@ifnextchar[{\@mglplot}{\@mglplot[]}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@mglplot} +% This command receives one mandatory argument, but enclosed between brackets; so it receives the optional argument of |\mglplot|. +% \begin{macrocode} +\def\@mglplot[#1]{% +% \end{macrocode} +% Unless overwritten by the user with the |setup=\meta{setup}| option, the default setup is ``generic''; initialize the |\graph@keys| macro; process the \meta{key}=\meta{value} pairs passed by the user; increase the counter |mgl@image@no| for numbering and naming of images. +% \begin{macrocode} + \def\mglplot@setup{generic}% + \def\graph@keys{}% + \setkeys{mglplot@keys}{#1}% + \stepcounter{mgl@image@no}% +% \end{macrocode} +% If the given setup is undefined, issue a package error; otherwise, execute the buffer of the setup, which will write the contents of the corresponding |mglsetup| blocks to the general script. +% \begin{macrocode} + \ifx\csname mgl@setup@\mglplot@setup\endcsname\@undefined% + \PackageError{\mgl@name}{Setup "\mglplot@setup" undefined}{}% \else% - \def\next@action{% - \item\mbox{\this@line}% - \mglblock@read@line% - }% + \csname mgl@setup@\mglplot@setup\endcsname% \fi% - \next@action% +% \end{macrocode} +% Call |\@@mglplot| (see below). +% \begin{macrocode} + \@@mglplot% } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@@mglplot} +% This command writes its argument verbatim to the main script, then writes the command to save the corresponding image, and the \emph{reset} command to prepare MathGL for the next image; finally, it uses the |\mgl@include@image| to include the corresponding graphics in the document. +% \begin{macrocode} +\long\def\@@mglplot#1{% + \mgl@write\mgl@script{\detokenize{#1}}% + \mgl@write\mgl@script{% + write '\mgl@dir\jobname-mgl-\arabic{mgl@image@no}\mgl@image@ext'% + }% + \mgl@write\mgl@script{reset}% + \mgl@include@image{\mgl@dir\jobname-mgl-\arabic{mgl@image@no}}% +} +% \end{macrocode} +% \end{macro} +% \subsection{Verbatim-like environments} +% \begin{macro}{mgl@verb@line@no} +% \noindent We create a counter to number the lines of code in verbatim-like environments. +% \begin{macrocode} \newcounter{mgl@verb@line@no} +% \end{macrocode} +% \end{macro} +% \begin{environment}{mglverbatim} +% This environment writes its contents \emph{verbatim} to the \LaTeX{} document, numbering each line of code. +% \begin{macro}{\mglverbatim} +% The beginning of the |mglverbatim| environment. +% \begin{macrocode} + \def\mglverbatim{% +% \end{macrocode} +% Initialize the counter for lines of code. +% \begin{macrocode} \setcounter{mgl@verb@line@no}{0}% +% \end{macrocode} +% We use the list environment to set the numeration of the lines of code that will be written to the \LaTeX{} document as items of the list. We also set the separation between lines of code, the indentation of the line, and some other length parameters. +% \begin{macrocode} \list{\itshape\footnotesize\arabic{mgl@verb@line@no}.}{}% \setlength{\labelsep}{1em}% \itemsep\z@skip% \leftskip\z@skip\rightskip\z@skip% - \verbatim@font% \parindent\z@\parfillskip\@flushglue\parskip\z@skip% +% \end{macrocode} +% We do the same changes of categories as in the |mglcode| environment. +% \begin{macrocode} \let\do\@makeother \dospecials% \endlinechar`\^^M \catcode`\^^M\active% \obeyspaces% - \mglverbatim@ignore@line% +% \end{macrocode} +% use verbatim font. +% \begin{macrocode} + \verbatim@font% +% \end{macrocode} +% Call the command that will write each line of the contents of the environment. +% \begin{macrocode} + \expandafter\mglverbatim@ignore@line% } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglverbatim@ignore@line} +% This command ignores the first line of the |verbatim| environment, which is an empty line. +% \begin{macrocode} \def\mglverbatim@ignore@line#1{% - \mglverbatim@write@line% + \expandafter\mglverbatim@write@line% } -\newtoks\mgl@word -\newtoks\mgl@line +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglverbatim@write@line} +% Reads the contents of the |mglverbatim| character by character, and stores words in the |\mgl@word| buffer and lines in the |\mgl@line| buffer, just like the |mglcode| environment did. +% \begin{macrocode} \def\mglverbatim@write@line#1{% +% \end{macrocode} +% Unless overwritten later, the next action (|\next@action|) is recursively call |\mglverbatim@write@line|. +% \begin{macrocode} \let\next@action\mglverbatim@write@line% +% \end{macrocode} +% If the character read is an end-line character, +% \begin{macrocode} \expandafter\if#1\^^M% +% \end{macrocode} +% increase the line of code counter, write the line contained in |\mgl@line| as an item of the |list| environment, and clean |\mgl@word| and |\mgl@line|; +% \begin{macrocode} \stepcounter{mgl@verb@line@no}% \item\mbox{\the\mgl@line}% - \mgl@line{}% \mgl@word{}% + \mgl@line{}% +% \end{macrocode} +% if the character is a space, clean |\mgl@wors|, but add the space to |\mgl@line|; +% \begin{macrocode} \else\expandafter\if#1\space% \mgl@word{}% \mgl@line\expandafter{\the\mgl@line#1}% +% \end{macrocode} +% otherwise, the character is aphanumeric, so add it to the |\mgl@word| and |\mgl@line| buffers, and check if |\mgl@word| is |\end{mglverbatim}|, in which case overwrite |\next@action| to be that command. +% \begin{macrocode} \else% \mgl@word\expandafter{\the\mgl@word#1}% \mgl@line\expandafter{\the\mgl@line#1}% @@ -750,6 +1568,12 @@ \fi\fi% \next@action% } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\end@mglverbatim} +% \begin{macro}{\test@end@mglverbatim} +% We already know the purpose of these macros. +% \begin{macrocode} \begingroup% \escapechar=-1\relax% \xdef\end@mglverbatim{\string\\end\string\{mglverbatim\string\}}% @@ -760,31 +1584,361 @@ \def\next@action{\end{mglverbatim}}% \fi% } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macrocode} +% \end{macrocode} +% \begin{macro}{\endmglverbaim} +% The end of the |mglverbatim| environment. It just closes the |list| environment. +% \begin{macrocode} \def\endmglverbatim{\endlist} +% \end{macrocode} +% \end{macro} +% \end{environment} +% \begin{environment}{mglblock} +% This environment writes its contents to a script, whose name is passed as mandatory argument, ad then it also writes its contents to the \LaTeX{} document, numbering each line. +% \begin{macro}{\mglblock} +% The beginning of the |mglblock environment|. +% \begin{macrocode} + +\def\mglblock#1{% +% \end{macrocode} +% Check if the script already exists, in which case we issue a warning, but proceed anyway. +% \begin{macrocode} + \test@mgl@script@written{#1}% +% \end{macrocode} +% Add the name of the script to the list of scripts written. +% \begin{macrocode} + \xdef\mgl@script@written{\mgl@script@written#1,}% +% \end{macrocode} +% We make the same changes of categories as in the |mglcode| environment. +% \begin{macrocode} + \let\do\@makeother \dospecials% + \endlinechar`\^^M \catcode`\^^M\active% + \obeyspaces% +% \end{macrocode} +% Open the output stream for the current script. +% \begin{macrocode} + \def\this@script{#1}% + \if@mgltex@on@% + \immediate\openout\mgl@out@stream="\mgl@dir\this@script.mgl"% + \mglsignature@write\mgl@out@stream% + \fi% +% \end{macrocode} +% Call the command that will write each line of the contents of the environment. +% \begin{macrocode} + \expandafter\mglblock@write@line% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglblock@write@line} +% This macro reads characater by character the code inside |mglblock|, and uses the |\mgl@word| and |\mgl@line| buffers to store words and lines of codes, just like we did with the |mglcode| environment. +% \begin{macrocode} +\def\mglblock@write@line#1{% +% \end{macrocode} +% The next action (|\next@action|) is set to recursively call |\mglblock@write@line|, unless it is overwritten later. +% \begin{macrocode} + \let\next@action\mglblock@write@line% +% \end{macrocode} +% If the read character is an end-line character, write the contents of |\mgl@line| to the script, and the clean |\mgl@word| and |\mgl@line|; +% \begin{macrocode} + \expandafter\if#1\^^M% + \mgl@write\mgl@out@stream{\the\mgl@line}% + \mgl@word{}% + \mgl@line{}% +% \end{macrocode} +% if the read character if a space, clean |\mgl@word|, but add the space to |\mgl@line|; +% \begin{macrocode} + \else\expandafter\if#1\space% + \mgl@word{}% + \mgl@line\expandafter{\the\mgl@line#1}% +% \end{macrocode} +% otherwise, the character is alphnumeric, and should be added to |\mgl@word| and |\mgl@line|, and we test if |\mgl@word| is |\end{mglblock}|, in which case, we overwrite |\next@action| to that command. +% \begin{macrocode} + \else% + \mgl@word\expandafter{\the\mgl@word#1}% + \mgl@line\expandafter{\the\mgl@line#1}% + \test@end@mglblock{\the\mgl@word}% + \fi\fi% +% \end{macrocode} +% Execute |\next@action|. +% \begin{macrocode} + \next@action% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\end@mglblock} +% \begin{macro}{\test@end@mglblock} +% We already know the purpose of these macros. +% \begin{macrocode} +\begingroup% + \escapechar=-1\relax% + \xdef\end@mglblock{\string\\end\string\{mglblock\string\}}% +\endgroup% +\def\test@end@mglblock#1{% + \edef\this@word{#1}% + \ifx\this@word\end@mglblock% + \def\next@action{\end{mglblock}}% + \fi% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\mgl@in@stream} +% We create an input stream to read from MGL scripts. +% \begin{macrocode} +\newread\mgl@in@stream +% \end{macrocode} +% \end{macro} +% \begin{macro}{\endmglblock} +% The end of the |mglblock| environment. +% \begin{macrocode} +\def\endmglblock{% +% \end{macrocode} +% Close the output stream. +% \begin{macrocode} + \immediate\closeout\mgl@out@stream% +% \end{macrocode} +% Open the input stream. +% \begin{macrocode} + \immediate\openin\mgl@in@stream="\mgl@dir\this@script.mgl"% +% \end{macrocode} +% Here, we use the |list| environment to set the numeration of the lines of code that will be written to the \LaTeX{} document as items of the list. We also set the separation between lines of code, the indentation of the line, and some other lenght parameters. +% \begin{macrocode} + \begingroup% + \list{\itshape\footnotesize\arabic{mgl@verb@line@no}.}{}% + \setlength{\labelsep}{1em}% + \itemsep\z@skip% + \leftskip\z@skip\rightskip\z@skip% + \parindent\z@\parfillskip\@flushglue\parskip\z@skip% +% \end{macrocode} +% Use the verbatim font, and obey spaces, including spaces at the beggining of the line. +% \begin{macrocode} + \verbatim@font% + \@vobeyspaces% +% \end{macrocode} +% Call the command that will write the lines of code to the \LaTeX{} document. +% \begin{macrocode} + \mglblock@read@line% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglblock@read@line} +% This command reads lines of code from the input stream and writes them as items of the |list| environment. +% \begin{macrocode} +\def\mglblock@read@line{% +% \end{macrocode} +% Increase the line counter. +% \begin{macrocode} + \stepcounter{mgl@verb@line@no}% +% \end{macrocode} +% Read a line from the input stream. +% \begin{macrocode} + \read\mgl@in@stream to \this@line% +% \end{macrocode} +% If the end of file has been reached, define |\next@action| to close the input stream, and en the |list| environment; +% \begin{macrocode} + \ifeof\mgl@in@stream% + \def\next@action{% + \immediate\closein\mgl@in@stream% + \endlist% + \endgroup% + }% +% \end{macrocode} +% otherwise, |\next@action| is write the read line as an item of the |list| environment, and recursively call |\mglblock@read@line|. +% \begin{macrocode} + \else% + \def\next@action{% + \item\mbox{\this@line}% + \mglblock@read@line% + }% + \fi% +% \end{macrocode} +% Execute |\next@action|. +% \begin{macrocode} + \next@action% +} +% \end{macrocode} +% \end{macro} +% \end{environment} +% \subsection{Working with external scripts} +% \begin{macro}{\mglgraphics} +% This command allows to generate and include graphics from a external (not embedded) script. +% \begin{macrocode} \newcommand\mglgraphics[2][]{% +% \end{macrocode} +% Initialize |\graph@keys|, which will contain the \meta{key}=\meta{value} options for the |\includegraphics|command. +% \begin{macrocode} \def\graph@keys{}% +% \end{macrocode} +% Process the \meta{key}=\meta{value} options passed by the user. +% \begin{macrocode} \setkeys{mgl@keys}{#1}% - \immediate\write18{mglconv "\mgl@dir#2.mgl" -o "\mgl@dir#2\mgl@image@ext"} +% \end{macrocode} +% Execute the program |mglconv| (included in MathGL) to compile the corresponding script. +% \begin{macrocode} + \mgl@write{18}{mglconv "\mgl@dir#2.mgl" -s "\mgl@dir\mglcommonscript.mgl" -o "\mgl@dir#2\mgl@image@ext"} +% \end{macrocode} +% Include the generated image with the |\mgl@include@image| command. +% \begin{macrocode} \mgl@include@image{\mgl@dir#2}% } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglinclude} +% This command copies verbatim the contents of an external script, and numerates each line of code. +% \begin{macrocode} \def\mglinclude#1{% +% \end{macrocode} +% Initialize the line counter. +% \begin{macrocode} \setcounter{mgl@verb@line@no}{0}% +% \end{macrocode} +% Open the script in the input stream. +% \begin{macrocode} \immediate\openin\mgl@in@stream="\mgl@dir#1.mgl"% +% \end{macrocode} +% Here, we use the |list| environment to numerate each line of code as an item. We also set some length parameters. +% \begin{macrocode} \begingroup% \list{\itshape\footnotesize\arabic{mgl@verb@line@no}.}{}% \setlength{\labelsep}{1em}% \itemsep\z@skip% \leftskip\z@skip\rightskip\z@skip% - \verbatim@font% \parindent\z@\parfillskip\@flushglue\parskip\z@skip% +% \end{macrocode} +% We do the same changes of category as in the |mglcode| environment, and set the font to verbatim font. +% \begin{macrocode} \let\do\@makeother \dospecials% \endlinechar`\^^M \catcode`\^^M\active% \@vobeyspaces% + \verbatim@font% +% \end{macrocode} +% We (re)use the |\mglblock@read@line| command to numerate and write each line of code. +% \begin{macrocode} \mglblock@read@line% } +% \end{macrocode} +% \end{macro} +% \subsection{Additional commands} +% \begin{macro}{\mgldir} +% A command to specify a directory to write the scripts and create the images. +% First, we create a macro that will store the specified directory for later use. +% \begin{macrocode} + +\def\mgl@dir{} +% \end{macrocode} +% The command |\mgldir| is the only way to modify |\mgl@dir|. This is done so the user won't be able to modify the default directory, dangerously altering the internal behavior of the package. +% \begin{macrocode} +\def\mgldir#1{% + \def\mgl@dir{#1}% +} +% \end{macrocode} +% Declare |\mgldir| so that it can only be used in the preamble. This is because the main script \meta{document}.mgl is opened at the moment of the |\begin{document}| instruction. +% \begin{macrocode} +\@onlypreamble\mgldir +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mgl@quality} +% We define a macro to store the quality. +% \begin{macrocode} +\def\mgl@quality{2} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglquality} +% This is used to define the quality for MGL graphics. +% \begin{macrocode} +\def\mglquality#1{% +% \end{macrocode} +% Write the quality command to a setup script. +% \begin{macrocode} + \def\mgl@quality{#1}% + \if@mgltex@on@% + \immediate\openout\mgl@out@stream="\mgl@dir\mglcommonscript.mgl"% + \mgl@write\mgl@out@stream{quality #1}% + \immediate\closeout\mgl@out@stream% +% \end{macrocode} +% Print an info message about the corresponding quality, or a warning if the quality doesn't exist. +% \begin{macrocode} + \ifcase#1 + \PackageInfo{mgltex}{Quality 0: No face drawing (fastest)}% + \or% + \PackageInfo{mgltex}{Quality 1: No color interpolation (fast)}% + \or% + \PackageInfo{mgltex}{Quality 2: High quality (normal)}% + \or% + \PackageInfo{mgltex}{Quality 3: High quality with 3d primitives (not implemented yet)}% + \or% + \PackageInfo{mgltex}{Quality 4: No face drawing, direct bitmap drawing (low memory usage)}% + \or% + \PackageInfo{mgltex}{Quality 5: No color interpolation, direct bitmap drawing (low memory usage)}% + \or% + \PackageInfo{mgltex}{Quality 6: High quality, direct bitmap drawing (low memory usage)}% + \or% + \PackageInfo{mgltex}{Quality 7: High quality with 3d primitives, direct bitmap drawing (not implemented yet)}% + \or% + \PackageInfo{mgltex}{Quality 8: Draw dots instead of primitives (extremely fast)}% + \else% + \PackageWarning{mgltex}{Quality #1 not available. Using default (2)}% + \fi% + \else% + \PackageWarning{mgltex}{mglTeX is off, quality changes won't have effect}% + \fi% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mgltexon} +% \changes{v.2.0}{2014/11/15}{Add the command \texttt{\textbackslash mgltexon}} +% Has the same effect as the package option |on|, but its effect is local, meaning that works only from the point this command is called on. +% \begin{macrocode} + +\def\mgltexon{ + \@mgltex@on@true + \def\mgl@write##1##2{% + \immediate\write##1{##2}% + } +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mgltexoff} +% \changes{v.2.0}{2014/11/15}{Add the command \texttt{\textbackslash mgltexoff}} +% Has the same effect as the package option |off|, but its effect is local. +% \begin{macrocode} +\def\mgltexoff{% + \@mgltex@on@false + \def\mgl@write##1##2{}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglcomments} +% \changes{v2.0}{2014/11/22}{Add the command \texttt{\textbackslash mglcomments}} +% Has the same effect as the package option |comments|, but its effect is local, meaning that works only from the point this command is called on. +% \begin{macrocode} + +\def\mglcomments{ + \@mgl@comments@true +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglnocomments} +% \changes{v2.0}{2014/11/22}{Add the command \texttt{\textbackslash mglnocomments}} +% Has the same effect as the package option |off|, but its effect is local. +% \begin{macrocode} +\def\mglnocomments{% + \@mgl@comments@false +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mglTeX} +% Just pretty-prints the name of the package. +% \begin{macrocode} \def\mglTeX{mgl\TeX} % \end{macrocode} +% \end{macro} + + % \Finale \ No newline at end of file diff --git a/mgltex/mgltex.ins b/mgltex/mgltex.ins new file mode 100644 index 0000000..f780ff3 --- /dev/null +++ b/mgltex/mgltex.ins @@ -0,0 +1,61 @@ +%% +%% Copyright (C) 2014 by Diego Sejas +%% +%% This program is free software: you can redistribute it and/or modify it +%% under the terms of the GNU General Public License as published by the +%% Free Software Foundation, either version 3 of the License, or (at your +%% option) any later version. +%% +%% This program is distributed in the hope that it will be useful, but +%% WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +%% Public License for more details. +%% +%% You should have received a copy of the GNU General Public License along +%% with this program. If not, see . +%% + +\input docstrip.tex +\keepsilent + +\usedir{tex/latex/mgltex} + +\preamble + +This is a generated file. + +Copyright (C) 2014 by Diego Sejas + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation, either version 3 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see . + +\endpreamble + +\generate{\file{mgltex.sty}{\from{mgltex.dtx}{package}}} + +\obeyspaces +\Msg{**********************************************************} +\Msg{* *} +\Msg{* To finish the installation you have to move the *} +\Msg{* following file into a directory searched by TeX: *} +\Msg{* *} +\Msg{* mgltex.sty *} +\Msg{* *} +\Msg{* To produce the documentation run the file mgltex.dtx *} +\Msg{* through LaTeX. *} +\Msg{* *} +\Msg{* Happy TeXing! *} +\Msg{* *} +\Msg{**********************************************************} + +\endbatchfile \ No newline at end of file diff --git a/mgltex/mgltex.installer b/mgltex/mgltex.installer deleted file mode 100644 index f780ff3..0000000 --- a/mgltex/mgltex.installer +++ /dev/null @@ -1,61 +0,0 @@ -%% -%% Copyright (C) 2014 by Diego Sejas -%% -%% This program is free software: you can redistribute it and/or modify it -%% under the terms of the GNU General Public License as published by the -%% Free Software Foundation, either version 3 of the License, or (at your -%% option) any later version. -%% -%% This program is distributed in the hope that it will be useful, but -%% WITHOUT ANY WARRANTY; without even the implied warranty of -%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -%% Public License for more details. -%% -%% You should have received a copy of the GNU General Public License along -%% with this program. If not, see . -%% - -\input docstrip.tex -\keepsilent - -\usedir{tex/latex/mgltex} - -\preamble - -This is a generated file. - -Copyright (C) 2014 by Diego Sejas - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation, either version 3 of the License, or (at your -option) any later version. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see . - -\endpreamble - -\generate{\file{mgltex.sty}{\from{mgltex.dtx}{package}}} - -\obeyspaces -\Msg{**********************************************************} -\Msg{* *} -\Msg{* To finish the installation you have to move the *} -\Msg{* following file into a directory searched by TeX: *} -\Msg{* *} -\Msg{* mgltex.sty *} -\Msg{* *} -\Msg{* To produce the documentation run the file mgltex.dtx *} -\Msg{* through LaTeX. *} -\Msg{* *} -\Msg{* Happy TeXing! *} -\Msg{* *} -\Msg{**********************************************************} - -\endbatchfile \ No newline at end of file diff --git a/mgltex/mgltex.pdf b/mgltex/mgltex.pdf index 61542e9..fb4fedf 100644 Binary files a/mgltex/mgltex.pdf and b/mgltex/mgltex.pdf differ diff --git a/mgltex/mgltex.sty b/mgltex/mgltex.sty index 33fea4b..a4eb204 100644 --- a/mgltex/mgltex.sty +++ b/mgltex/mgltex.sty @@ -23,25 +23,42 @@ %% You should have received a copy of the GNU General Public License along %% with this program. If not, see . %% -\def\mgl@name{mgltex} -\def\mgl@date{2014/09/16} -\def\mgl@version{1.0} -\def\mgl@description{Embed MGL code into LaTeX documents} - \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{\mgl@name}[\mgl@date\space v.\mgl@version\space\mgl@description] +\ProvidesPackage{mgltex}[/2014/11/22 v2.0 Embed MGL scripts in LaTeX documents] + \RequirePackage{keyval} \RequirePackage{graphicx} + \DeclareOption{draft}{% \PassOptionsToPackage{\CurrentOption}{graphicx}% } \DeclareOption{final}{% \PassOptionsToPackage{\CurrentOption}{graphicx}% } +\newif\if@mgltex@on@ +\DeclareOption{on}{% + \@mgltex@on@true% + \def\mgl@write#1#2{% + \immediate\write#1{#2}% + } +} +\DeclareOption{off}{% + \@mgltex@on@false% + \def\mgl@write#1#2{}% +} +\newif\if@mgl@comments@ +\DeclareOption{comments}{% + \@mgl@comments@true% +} +\DeclareOption{nocomments}{% + \@mgl@comments@false% +} -\DeclareGraphicsExtensions{.png,.eps,.jpg,.jpeg,.bps,.pdf,.epsz,.eps.gz,.bpsz,.bps.gz,.gif} +\DeclareGraphicsExtensions{% + .png,.eps,.jpg,.jpeg,.bps,.pdf,.epsz,.eps.gz,.bpsz,.bps.gz,.gif% +} \DeclareOption{jpg}{\def\mgl@image@ext{.jpg}} \DeclareOption{jpeg}{\def\mgl@image@ext{.jpeg}} @@ -54,8 +71,9 @@ \DeclareOption{gif}{\def\mgl@image@ext{.gif}} \DeclareOption{tex}{\def\mgl@image@ext{.tex}} +\DeclareOption*{\@unknownoptionerror} -\ExecuteOptions{final,eps} +\ExecuteOptions{final,on,nocomments,eps} \ProcessOptions* \define@key{mgl@keys}{bb}{\g@addto@macro{\graph@keys}{bb=#1,}} @@ -83,6 +101,7 @@ \define@key{mgl@keys}{command}{\g@addto@macro{\graph@keys}{command=#1,}} \define@key{mgl@keys}{imgext}{\def\mgl@image@ext{.#1}} + \define@key{mglplot@keys}{bb}{\g@addto@macro{\graph@keys}{bb=#1,}} \define@key{mglplot@keys}{bbllx}{\g@addto@macro{\graph@keys}{bbllx=#1,}} \define@key{mglplot@keys}{bblly}{\g@addto@macro{\graph@keys}{bblly=#1,}} @@ -106,116 +125,84 @@ \define@key{mglplot@keys}{ext}{\g@addto@macro{\graph@keys}{ext=#1,}} \define@key{mglplot@keys}{read}{\g@addto@macro{\graph@keys}{read=#1,}} \define@key{mglplot@keys}{command}{\g@addto@macro{\graph@keys}{command=#1,}} -\define@key{mglplot@keys}{outext}{\def\mglplot@output@ext{.#1}} -\define@key{mglplot@keys}{settings}{\def\mglplot@settings{#1}} +\define@key{mglplot@keys}{imgext}{\def\mglplot@image@ext{.#1}} +\define@key{mglplot@keys}{setup}{\def\mglplot@setup{#1}} -\def\mgl@dir{} -\def\mgldir#1{% - \def\mgl@dir{#1}% -} -\@onlypreamble\mgldir - -\newwrite\mgl@script -\AtBeginDocument{% - \immediate\openout\mgl@script="\mgl@dir\jobname.mgl"% -} -\AtEndDocument{% - \immediate\write\mgl@script{}% - \immediate\write\mgl@script{stop}% - \mgl@func% - \immediate\closeout\mgl@script% - \immediate\write18{mglconv -n "\mgl@dir\jobname.mgl"}% -} -\def\mglplotsettings@defined{} -\newcommand\mglplotsettings[1][generic]{% - \test@mglplotsettings@defined{#1}% - \expandafter\def\csname mgl@setup@#1\endcsname{\immediate\write\mgl@script{}}% - \g@addto@macro{\mglplotsettings@defined}{#1,}% - \let\do\@makeother \dospecials% - \endlinechar`\^^M \catcode`\^^M\active% - \catcode`\ =10% - \expandafter\mglplotsettings@write@line% -} -\def\test@mglplotsettings@defined#1{% - \def\this@setup{#1}% - \@for\mglplotsettings@name:=\mglplotsettings@defined\do{% - \ifx\this@mglplotsettings\mglplotsettings@name% - \PackageWarning{\mgl@name}{Redefining "#1" setup for \noexpand\mglplot}% - \fi% - }% -} -\begingroup% - \catcode`\^^M\active% - \gdef\mglplotsettings@write@line#1^^M{% - \def\next@action{% - \expandafter\g@addto@macro\csname mgl@setup@\this@setup\endcsname{\immediate\write\mgl@script{#1}}% - \mglplotsettings@write@line% +\def\TeX@ext{.tex} +\def\mgl@include@image#1{% + \ifx\mgl@image@ext\TeX@ext% + \IfFileExists{#1.tex}{% + \include{#1}% + }{% + \mgl@img@not@found{#1}% + }% + \else% + \def\next@action{\mgl@img@not@found{#1}}% + \@for\img@ext:=\Gin@extensions\do{% + \IfFileExists{#1\img@ext}{% + \def\next@action{% + \expandafter\includegraphics\expandafter[\graph@keys]{#1}% + }% + }{}% }% - \test@end@mglplotsettings{#1}% \next@action% - }% -\endgroup -\begingroup% - \escapechar=-1 \relax% - \xdef\end@mglplotsettings{\string\\end\string\{mglplotsettings\string\}}% -\endgroup -\def\test@end@mglplotsettings#1{% - \edef\this@line{#1}% - \ifx\this@line\end@mglplotsettings% - \def\next@action{\end{mglplotsettings}}% \fi% } -\def\endmglplotsettings{} +\def\mgl@img@not@found#1{% + \PackageWarning{mgltex}{MGL image "#1" not found}% + \framebox[10em]{% + \centering% + \bfseries\Huge% + \begin{tabular}{c}MGL\\image\\not\\found\end{tabular}% + }% +} -\def\TeX@ext{.tex} \newcounter{mgl@image@no} -\def\mglplot{% - \@ifnextchar[{\@mglplot}{\@mglplot[]}% -} -\def\@mglplot[#1]{% - \def\mglplot@settings{generic}% - \def\graph@keys{}% - \setkeys{mglplot@keys}{#1}% - \stepcounter{mgl@image@no}% - \ifx\csname mgl@setup@\mglplot@settings\endcsname\@undefined% - \PackageError{\mgl@name}{Setup "\mglplot@settings" undefined}{}% - \else% - \csname mgl@setup@\mglplot@settings\endcsname% +\newwrite\mgl@script +\AtBeginDocument{% + \if@mgltex@on@% + \immediate\openout\mgl@script="\mgl@dir\jobname.mgl"% + \mglsignature@write\mgl@script% \fi% - \@@mglplot% } -\long\def\@@mglplot#1{% - \immediate\write\mgl@script{\detokenize{#1}}% - \immediate\write\mgl@script{write '\mgl@dir\jobname-mgl-\arabic{mgl@image@no}\mgl@image@ext'}% - \immediate\write\mgl@script{reset}% - \mgl@include@image{\mgl@dir\jobname-mgl-\arabic{mgl@image@no}}% +\AtEndDocument{% + \mgl@write\mgl@script{}% + \mgl@write\mgl@script{stop}% + \mgl@func% + \immediate\closeout\mgl@script% + \mgl@write{18}{mglconv -n "\mgl@dir\jobname.mgl"}% } + \newcommand\mgl[1][]{% \def\graph@keys{}% \setkeys{mgl@keys}{#1}% \let\do\@makeother \dospecials% \endlinechar`\^^M \catcode`\^^M\active% \catcode`\ =10% - \mgl@write@line% + \mgl@write\mgl@script{quality \mgl@quality}% + \expandafter\mgl@write@line% } \begingroup% \escapechar=-1 \relax% \xdef\end@mgl{\string\\end\string\{mgl\string\}}% \endgroup + \begingroup% + \catcode`\^^M\active% \gdef\mgl@write@line#1^^M{% \def\next@action{% - \immediate\write\mgl@script{#1}% + \mgl@write\mgl@script{#1}% \mgl@write@line% }% \test@end@mgl{#1}% \next@action% }% \endgroup + \def\test@end@mgl#1{% \edef\this@line{#1}% \ifx\this@line\end@mgl% @@ -224,36 +211,12 @@ } \def\endmgl{% \stepcounter{mgl@image@no}% - \immediate\write\mgl@script{write '\mgl@dir\jobname-mgl-\arabic{mgl@image@no}\mgl@image@ext'}% - \immediate\write\mgl@script{reset}% - \mgl@include@image{\mgl@dir\jobname-mgl-\arabic{mgl@image@no}}% -} -\def\mgl@include@image#1{% - \ifx\mgl@image@ext\TeX@ext% - \IfFileExists{#1.tex}{% - \include{#1}% - }{% - \mgl@img@not@found{#1}% - }% - \else% - \def\next@action{\mgl@img@not@found{#1}}% - \@for\img@ext:=\Gin@extensions\do{% - \IfFileExists{#1\img@ext}{% - \def\next@action{% - \expandafter\includegraphics\expandafter[\graph@keys]{#1}% - }% - }{}% - }% - \next@action% - \fi% -} -\def\mgl@img@not@found#1{% - \PackageWarning{\mgl@name}{MGL image "#1" not found}% - \framebox[10em]{% - \centering% - \bfseries\Huge% - \vbox{MGL\\image\\not\\found}% + \mgl@write\mgl@script{% + write '\mgl@dir\jobname-mgl-\arabic{mgl@image@no}\mgl@image@ext'% }% + \mgl@write\mgl@script{reset}% + \mgl@write\mgl@script{}% + \mgl@include@image{\mgl@dir\jobname-mgl-\arabic{mgl@image@no}}% } \bgroup% @@ -278,26 +241,31 @@ \test@mgl@script@written{#2}% \xdef\mgl@script@written{\mgl@script@written#2,}% \def\this@script{#2}% - \immediate\openout\mgl@out@stream=\mgl@dir\this@script.mgl% + \if@mgltex@on@% + \immediate\openout\mgl@out@stream=\mgl@dir\this@script.mgl% + \mglsignature@write\mgl@out@stream% + \fi% \let\do\@makeother \dospecials% \endlinechar`\^^M \catcode`\^^M\active% \obeyspaces% - \mglcode@write@line% + \expandafter\mglcode@write@line% } \def\test@mgl@script@written#1{% \edef\this@script{#1}% \@for\mgl@script@name:=\mgl@script@written\do{% \ifx\this@script\mgl@script@name% - \PackageWarning{\mgl@name}{Overwriting MGL script "\this@script.mgl"}% + \PackageWarning{mgltex}{Overwriting MGL script "\this@script.mgl"}% \fi% }% } +\newtoks\mgl@word +\newtoks\mgl@line \def\mglcode@write@line#1{% \let\next@action\mglcode@write@line% \expandafter\if#1\^^M% - \immediate\write\mgl@out@stream{\the\mgl@line}% - \mgl@line{}% + \mgl@write\mgl@out@stream{\the\mgl@line}% \mgl@word{}% + \mgl@line{}% \else\expandafter\if#1\space% \mgl@word{}% \mgl@line\expandafter{\the\mgl@line#1}% @@ -320,7 +288,9 @@ } \def\endmglcode{% \immediate\closeout\mgl@out@stream% - \immediate\write18{mglconv "\mgl@dir\this@script.mgl" -o "\mgl@dir\this@script\mgl@image@ext"}% + \mgl@write{18}{% + mglconv "\mgl@dir\this@script.mgl" -s "\mgl@dir\mglcommonscript.mgl" -o "\mgl@dir\this@script\mgl@image@ext"% + }% \mgl@include@image{\mgl@dir\this@script}% } @@ -342,15 +312,16 @@ \def\mglfunc@defined{} \def\mgl@func{} + \newcommand\mglfunc[2][0]{% \test@mglfunc@defined{#2}% \g@addto@macro{\mglfunc@defined}{#2,}% \let\do\@makeother \dospecials% \endlinechar`\^^M \catcode`\^^M\active% \catcode`\ =10% - \g@addto@macro{\mgl@func}{\immediate\write\mgl@script{}}% - \g@addto@macro{\mgl@func}{\immediate\write\mgl@script{func '#2' #1}}% - \expandafter\mglfunc@ignore@line% + \g@addto@macro{\mgl@func}{\mgl@write\mgl@script{}}% + \g@addto@macro{\mgl@func}{\mgl@write\mgl@script{func '#2' #1}}% + \expandafter\mglfunc@write@line% } \def\test@mglfunc@defined#1{% \def\this@func{#1}% @@ -362,13 +333,10 @@ } \begingroup% \catcode`\^^M\active% - \gdef\mglfunc@ignore@line#1^^M{% - \expandafter\mglfunc@write@line% - } \gdef\mglfunc@write@line#1^^M{% \def\next@action{% - \g@addto@macro{\mgl@func}{\immediate\write\mgl@script{#1}}% - \mglfunc@write@line% + \g@addto@macro{\mgl@func}{\mgl@write\mgl@script{#1}}% + \expandafter\mglfunc@write@line% }% \test@end@mglfunc{#1}% \next@action% @@ -385,28 +353,228 @@ \fi% } \def\endmglfunc{% - \g@addto@macro{\mgl@func}{\immediate\write\mgl@script{return}}% + \g@addto@macro{\mgl@func}{\mgl@write\mgl@script{return}}% } + +\def\mglcommonscript{mgl_common_script} +\bgroup% + \escapechar=-1\relax% + \xdef\end@mglcommon{\string\\end\string\{mglcommon\string\}}% +\egroup% +\newenvironment{mglcommon}{% + \def\test@end@mglcode##1{% + \edef\this@word{##1}% + \ifx\this@word\end@mglcommon% + \def\next@action{\end{mglcommon}}% + \fi% + }% + \mglcode{\mglcommonscript}% +}{% + \mgl@write\mgl@out@stream{quality \mgl@quality}% + \immediate\closeout\mgl@out@stream% +} +\@onlypreamble\mglcommon +\bgroup + \catcode`#=12 + \gdef\mglcomm{#} +\egroup +\def\mgltexsignature{% + \mglcomm^^J% + \mglcomm\space This file was autogenerated from the document \jobname.tex on date \today^^J% + \mglcomm% +} +\newcommand\mglsignature{% + \def\mgltexsignature{}% + \let\do\@makeother \dospecials% + \endlinechar`\^^M \catcode`\^^M\active% + \@vobeyspaces% + \expandafter\mglsignature@write@line% +} +\begingroup% + \escapechar=-1 \relax% + \xdef\end@mglsignature{\string\\end\string\{mglsignature\string\}}% +\endgroup +\begingroup% + \catcode`\^^M\active% + \gdef\mglsignature@write@line#1^^M{% + \def\next@action{% + \g@addto@macro{\mgltexsignature}{\mglcomm\space#1^^J} + \mglsignature@write@line% + }% + \test@end@mglsignature{#1}% + \next@action% + }% +\endgroup +\def\test@end@mglsignature#1{% + \edef\this@line{#1}% + \ifx\this@line\end@mglsignature% + \def\next@action{\end{mglsignature}}% + \fi% +} +\def\endmglsignature{% + \g@addto@macro{\mgltexsignature}{\mglcomm} +} +\def\mglsignature@write#1{\mgl@write#1{\mgltexsignature}} + +\def\mglcomment{% + \let\do\@makeother\dospecials% + \obeylines% + \@vobeyspaces% + \verbatim@font% + \small% + \mgl@comment% +} +\begingroup% + \catcode`|=0\catcode`[= 1\catcode`]=2\catcode`\{=12\catcode`\}=12\catcode`\\=12% + |gdef|mgl@comment#1\end{mglcomment}[% + |if@mgl@comments@% + |begin[center]% + <------------------ MGL comment ------------------>% + #1% + <------------------ MGL comment ------------------>% + |end[center]% + |fi% + |end[mglcomment]]% +|endgroup% +\def\endmglcomment{} + + +\def\mglsetup@defined{} +\newcommand\mglsetup[1][generic]{% + \test@mglsetup@defined{#1}% + \g@addto@macro{\mglsetup@defined}{#1,}% + \expandafter\def\csname mgl@setup@#1\endcsname{\mgl@write\mgl@script{}}% + \expandafter\def\csname mgl@setup@#1\endcsname{\mgl@write\mgl@script{quality \mgl@quality}}% + \let\do\@makeother \dospecials% + \endlinechar`\^^M \catcode`\^^M\active% + \catcode`\ =10% + \expandafter\mglsetup@write@line% +} +\def\test@mglsetup@defined#1{% + \def\this@setup{#1}% + \@for\mglsetup@name:=\mglsetup@defined\do{% + \ifx\this@mglsetup\mglsetup@name% + \PackageWarning{\mgl@name}{Redefining "#1" setup for \noexpand\mglplot}% + \fi% + }% +} +\begingroup% + \catcode`\^^M\active% + \gdef\mglsetup@write@line#1^^M{% + \def\next@action{% + \expandafter\g@addto@macro\csname mgl@setup@\this@setup\endcsname{% + \mgl@write\mgl@script{#1}% + }% + \expandafter\mglsetup@write@line% + }% + \test@end@mglsetup{#1}% + \next@action% + }% +\endgroup +\begingroup% + \escapechar=-1 \relax% + \xdef\end@mglsetup{\string\\end\string\{mglsetup\string\}}% +\endgroup +\def\test@end@mglsetup#1{% + \edef\this@line{#1}% + \ifx\this@line\end@mglsetup% + \def\next@action{\end{mglsetup}}% + \fi% +} +\def\endmglsetup{} + + +\def\mglplot{% + \@ifnextchar[{\@mglplot}{\@mglplot[]}% +} +\def\@mglplot[#1]{% + \def\mglplot@setup{generic}% + \def\graph@keys{}% + \setkeys{mglplot@keys}{#1}% + \stepcounter{mgl@image@no}% + \ifx\csname mgl@setup@\mglplot@setup\endcsname\@undefined% + \PackageError{\mgl@name}{Setup "\mglplot@setup" undefined}{}% + \else% + \csname mgl@setup@\mglplot@setup\endcsname% + \fi% + \@@mglplot% +} +\long\def\@@mglplot#1{% + \mgl@write\mgl@script{\detokenize{#1}}% + \mgl@write\mgl@script{% + write '\mgl@dir\jobname-mgl-\arabic{mgl@image@no}\mgl@image@ext'% + }% + \mgl@write\mgl@script{reset}% + \mgl@include@image{\mgl@dir\jobname-mgl-\arabic{mgl@image@no}}% +} + +\newcounter{mgl@verb@line@no} + +\def\mglverbatim{% + \setcounter{mgl@verb@line@no}{0}% + \list{\itshape\footnotesize\arabic{mgl@verb@line@no}.}{}% + \setlength{\labelsep}{1em}% + \itemsep\z@skip% + \leftskip\z@skip\rightskip\z@skip% + \parindent\z@\parfillskip\@flushglue\parskip\z@skip% + \let\do\@makeother \dospecials% + \endlinechar`\^^M \catcode`\^^M\active% + \obeyspaces% + \verbatim@font% + \expandafter\mglverbatim@ignore@line% +} +\def\mglverbatim@ignore@line#1{% + \expandafter\mglverbatim@write@line% +} +\def\mglverbatim@write@line#1{% + \let\next@action\mglverbatim@write@line% + \expandafter\if#1\^^M% + \stepcounter{mgl@verb@line@no}% + \item\mbox{\the\mgl@line}% + \mgl@word{}% + \mgl@line{}% + \else\expandafter\if#1\space% + \mgl@word{}% + \mgl@line\expandafter{\the\mgl@line#1}% + \else% + \mgl@word\expandafter{\the\mgl@word#1}% + \mgl@line\expandafter{\the\mgl@line#1}% + \test@end@mglverbatim{\the\mgl@word}% + \fi\fi% + \next@action% +} +\begingroup% + \escapechar=-1\relax% + \xdef\end@mglverbatim{\string\\end\string\{mglverbatim\string\}}% +\endgroup% +\def\test@end@mglverbatim#1{% + \edef\this@word{#1}% + \ifx\this@word\end@mglverbatim% + \def\next@action{\end{mglverbatim}}% + \fi% +} +\def\endmglverbatim{\endlist} + \def\mglblock#1{% \test@mgl@script@written{#1}% \xdef\mgl@script@written{\mgl@script@written#1,}% - \def\this@script{#1}% \let\do\@makeother \dospecials% \endlinechar`\^^M \catcode`\^^M\active% \obeyspaces% - \immediate\openout\mgl@out@stream="\mgl@dir\this@script.mgl"% - \mglblock@ignore@line% -} -\def\mglblock@ignore@line#1{% - \mglblock@write@line% + \def\this@script{#1}% + \if@mgltex@on@% + \immediate\openout\mgl@out@stream="\mgl@dir\this@script.mgl"% + \mglsignature@write\mgl@out@stream% + \fi% + \expandafter\mglblock@write@line% } \def\mglblock@write@line#1{% \let\next@action\mglblock@write@line% \expandafter\if#1\^^M% - \immediate\write\mgl@out@stream{\the\mgl@line}% - \mgl@line{}% + \mgl@write\mgl@out@stream{\the\mgl@line}% \mgl@word{}% + \mgl@line{}% \else\expandafter\if#1\space% \mgl@word{}% \mgl@line\expandafter{\the\mgl@line#1}% @@ -436,8 +604,8 @@ \setlength{\labelsep}{1em}% \itemsep\z@skip% \leftskip\z@skip\rightskip\z@skip% - \verbatim@font% \parindent\z@\parfillskip\@flushglue\parskip\z@skip% + \verbatim@font% \@vobeyspaces% \mglblock@read@line% } @@ -459,58 +627,10 @@ \next@action% } -\newcounter{mgl@verb@line@no} -\def\mglverbatim{% - \setcounter{mgl@verb@line@no}{0}% - \list{\itshape\footnotesize\arabic{mgl@verb@line@no}.}{}% - \setlength{\labelsep}{1em}% - \itemsep\z@skip% - \leftskip\z@skip\rightskip\z@skip% - \verbatim@font% - \parindent\z@\parfillskip\@flushglue\parskip\z@skip% - \let\do\@makeother \dospecials% - \endlinechar`\^^M \catcode`\^^M\active% - \obeyspaces% - \mglverbatim@ignore@line% -} -\def\mglverbatim@ignore@line#1{% - \mglverbatim@write@line% -} -\newtoks\mgl@word -\newtoks\mgl@line -\def\mglverbatim@write@line#1{% - \let\next@action\mglverbatim@write@line% - \expandafter\if#1\^^M% - \stepcounter{mgl@verb@line@no}% - \item\mbox{\the\mgl@line}% - \mgl@line{}% - \mgl@word{}% - \else\expandafter\if#1\space% - \mgl@word{}% - \mgl@line\expandafter{\the\mgl@line#1}% - \else% - \mgl@word\expandafter{\the\mgl@word#1}% - \mgl@line\expandafter{\the\mgl@line#1}% - \test@end@mglverbatim{\the\mgl@word}% - \fi\fi% - \next@action% -} -\begingroup% - \escapechar=-1\relax% - \xdef\end@mglverbatim{\string\\end\string\{mglverbatim\string\}}% -\endgroup% -\def\test@end@mglverbatim#1{% - \edef\this@word{#1}% - \ifx\this@word\end@mglverbatim% - \def\next@action{\end{mglverbatim}}% - \fi% -} -\def\endmglverbatim{\endlist} - \newcommand\mglgraphics[2][]{% \def\graph@keys{}% \setkeys{mgl@keys}{#1}% - \immediate\write18{mglconv "\mgl@dir#2.mgl" -o "\mgl@dir#2\mgl@image@ext"} + \mgl@write{18}{mglconv "\mgl@dir#2.mgl" -s "\mgl@dir\mglcommonscript.mgl" -o "\mgl@dir#2\mgl@image@ext"} \mgl@include@image{\mgl@dir#2}% } @@ -522,15 +642,72 @@ \setlength{\labelsep}{1em}% \itemsep\z@skip% \leftskip\z@skip\rightskip\z@skip% - \verbatim@font% \parindent\z@\parfillskip\@flushglue\parskip\z@skip% \let\do\@makeother \dospecials% \endlinechar`\^^M \catcode`\^^M\active% \@vobeyspaces% + \verbatim@font% \mglblock@read@line% } +\def\mgl@dir{} +\def\mgldir#1{% + \def\mgl@dir{#1}% +} +\@onlypreamble\mgldir +\def\mgl@quality{2} +\def\mglquality#1{% + \def\mgl@quality{#1}% + \if@mgltex@on@% + \immediate\openout\mgl@out@stream="\mgl@dir\mglcommonscript.mgl"% + \mgl@write\mgl@out@stream{quality #1}% + \immediate\closeout\mgl@out@stream% + \ifcase#1 + \PackageInfo{mgltex}{Quality 0: No face drawing (fastest)}% + \or% + \PackageInfo{mgltex}{Quality 1: No color interpolation (fast)}% + \or% + \PackageInfo{mgltex}{Quality 2: High quality (normal)}% + \or% + \PackageInfo{mgltex}{Quality 3: High quality with 3d primitives (not implemented yet)}% + \or% + \PackageInfo{mgltex}{Quality 4: No face drawing, direct bitmap drawing (low memory usage)}% + \or% + \PackageInfo{mgltex}{Quality 5: No color interpolation, direct bitmap drawing (low memory usage)}% + \or% + \PackageInfo{mgltex}{Quality 6: High quality, direct bitmap drawing (low memory usage)}% + \or% + \PackageInfo{mgltex}{Quality 7: High quality with 3d primitives, direct bitmap drawing (not implemented yet)}% + \or% + \PackageInfo{mgltex}{Quality 8: Draw dots instead of primitives (extremely fast)}% + \else% + \PackageWarning{mgltex}{Quality #1 not available. Using default (2)}% + \fi% + \else% + \PackageWarning{mgltex}{mglTeX is off, quality changes won't have effect}% + \fi% +} + +\def\mgltexon{ + \@mgltex@on@true + \def\mgl@write##1##2{% + \immediate\write##1{##2}% + } +} +\def\mgltexoff{% + \@mgltex@on@false + \def\mgl@write##1##2{}% +} + +\def\mglcomments{ + \@mgl@comments@true +} +\def\mglnocomments{% + \@mgl@comments@false +} + \def\mglTeX{mgl\TeX} + \endinput %% %% End of file `mgltex.sty'. diff --git a/mgltex/sample.tex b/mgltex/sample.tex index 7fcda3b..5fe94f8 100644 --- a/mgltex/sample.tex +++ b/mgltex/sample.tex @@ -1,22 +1,25 @@ -\documentclass[12pt]{article} +\documentclass{article} -\usepackage[png]{mgltex} +\usepackage[png,comments]{mgltex} \title{\mglTeX{} package example} \author{Diego Sejas Viscarra, Alexey Balakin} \date{\today} \mgldir{scripts/} +\begin{mglcommon} + define gravity 9.81 +\end{mglcommon} + \begin{document} \maketitle +\noindent The \LaTeX{} package \textsf{\mglTeX} (was made by Diego Sejas Viscarra) allows one to make figures directly from MGL scripts located in \LaTeX{} file. -LaTeX package \texttt{mgltex} (was made by Diego Sejas Viscarra) allow one to make figures directly from MGL script located in LaTeX file. - -For using this package you need to specify \texttt{--shell-escape} option for \emph{latex/pdflatex} or manually run \emph{mglconv} tool with produced MGL scripts for generation of images. Don't forgot to run \emph{latex/pdflatex} second time to insert generated images into the output document. +For using this package you need to specify \texttt{--shell-escape} option for \emph{latex/pdflatex} or manually run \emph{mglconv} tool on produced MGL scripts for generation of images. Don't forget to run \emph{latex/pdflatex} a second time to insert the generated images into the output document. -The package may have following options: \texttt{draft}, \texttt{final} -- the same as in the \emph{graphicx} package; \texttt{jpg}, \texttt{jpeg}, \texttt{png} -- for export to JPEG/PNG images; \texttt{eps}, \texttt{epsz} -- for export to uncompressed/compressed EPS format as primitives; \texttt{bps}, \texttt{bpsz} -- for export to uncompressed/compressed EPS format as bitmap (don't work with \emph{pdflatex}), \texttt{pdf} -- for export to 3D PDF. +The package may have following options: \texttt{draft}, \texttt{final} --- the same as in the \emph{graphicx} package; \texttt{on}, \texttt{off} --- to activate/deactivate the creation of scripts and graphics; \texttt{comments}, \texttt{nocomments} --- to make visible/invisible commentaries contained inside \texttt{mglcomment} environments; \texttt{jpg}, \texttt{jpeg}, \texttt{png} --- to export graphics as JPEG/PNG images; \texttt{eps}, \texttt{epsz} --- to export to uncompressed/compressed EPS format as primitives; \texttt{bps}, \texttt{bpsz} --- to export to uncompressed/compressed EPS format as bitmap (doesn't work with \emph{pdflatex}); \texttt{pdf} --- to export to 3D PDF; \texttt{tex} --- to export to \LaTeX{}/\emph{tikz} document. The package defines the following environments: \begin{description} @@ -36,22 +39,90 @@ The package defines the following environments: Exactly the same as \texttt{mglblock}, but it doesn't write to a file. This environment doesn't have arguments. \item[mglfunc] Is used to define MGL functions. It takes one mandatory argument, which is the name of the function, plus one additional argument, which specifies the number of arguments of the function. The environment needs to contain only the body of the function, since the first and last lines are appended automatically, and the resulting code is written at the end of the general script, which is also written automatically. The warning is produced if 2 or more function with the same name is defined. -\item[mglplotsettings] +\item[mglsignature] +Used to defined a commentary that will be added to every script. It is useful to include signature text or license text. Observe this is a verbatim-like environment, so no \LaTeX{} command will be executed inside it, but will be copied as is. + +As an alternative to this method of declaring signatures, the user can manually redefine the signature macro \texttt{\textbackslash{}mgltexsignature}, according to the following rules: + \begin{itemize} + \item The positions of the comment signs for the MGL language have to be manually specified in the signature using the \texttt{\textbackslash{}mglcomm} macro. + \item The new-line character is declared as ``\verb|^^J|''. + \item A percent sign (\texttt{\%}) has to be added at the end of every physical line of \texttt{\textbackslash{}mgltexsignature}, otherwise an inelegant space at the beginning of every line will appear. + \item Any \LaTeX{} command can be used in this case. +\end{itemize} + For example, the default signature: + \begin{quote}\small + \mglcomm\\ + \mglcomm\ This script was generated from $<$document$>$.mgl on date $<$today$>$\\ + \mglcomm + \end{quote} + can be achieved with + \begin{verbatim} + \def\mgltexsignature{% + \mglcomm^^J% + \mglcomm\ This script was generated from \jobname.mgl on date \today^^J% + \mglcomm% + } + \end{verbatim} +\item[mglcomment] + Used to contain multiline commentaries. This commentaries will be visible/invisible in the output document, depending on the use of the package options \texttt{comments} and \texttt{nocomments} (see above), or the \texttt{\mglcomments} and \texttt{\mglnocomments} commands (see bellow). + + When, bisible, the comment will appear like this: + \begin{center} + \makeatletter + \verbatim@font + \makeatother + <------------------ MGL comment ------------------>\\ + $<$Commentary$>$\\ + <------------------ MGL comment ------------------>\\ + \end{center} +\item[mglsetup] If many scripts with the same code are to be written, the repetitive code can be written inside this environment only once, then this code will be used automatically every time the \texttt{\textbackslash{}mglplot} command is used (see below). It takes one optional argument, which is a name to be associated to the corresponding contents of the environment; this name can be passed to the \texttt{\textbackslash{}mglplot} command to use the corresponding block of code automatically (see below). \end{description} The package also defines the following commands: \begin{description} \item[\textbackslash{}mglplot] - It takes one mandatory argument, which is MGL instructions separated by the symbol ':' this argument can be more than one line long. It takes the same optional arguments as the \texttt{mgl} environment, plus an additional argument \emph{settings}, which indicates the name associated to a block of code inside a \texttt{mglplotsettings} environment. The code inside the mandatory argument will be appended to the block of code specified, and the resulting code will be written to the general script. + It takes one mandatory argument, which is MGL instructions separated by the symbol ':' this argument can be more than one line long. It takes the same optional arguments as the \texttt{mgl} environment, plus an additional argument \emph{settings}, which indicates the name associated to a block of code inside a \texttt{mglsetup} environment. The code inside the mandatory argument will be appended to the block of code specified, and the resulting code will be written to the general script. \item[\textbackslash{}mglgraphics] This command takes the same optional arguments as the \texttt{mgl} environment, and one mandatory argument, which is the name of a MGL script. This command will compile the corresponding script and include the resulting image. It is useful when you have a script outside the LaTeX document, and you want to include the image, but you don't want to type the script again. \item[\textbackslash{}mglinclude] This is like \texttt{\textbackslash{}mglgraphics} but, instead of creating/including the corresponding image, it writes the contents of the MGL script to the LaTeX document, and numerates the lines. \item[\textbackslash{}mgldir] This command can be used in the preamble of the document to specify a directory where LaTeX will save the MGL scripts and generate the corresponding images. This directory is also where \texttt{\textbackslash{}mglgraphics} and \texttt{\textbackslash{}mglinclude} will look for scripts. +\item[\textbackslash{}mglquality] + Can be used to adjust the quality of the MGL graphics produced. The following table shows the available qualities: + \begin{center} + \begin{tabular}{cl} + \hline + Quality & Description\\ + \hline + \hline + $0$ & No face drawing (fastest)\\ + \hline + $1$ & No color interpolation (fast)\\ + \hline + $2$ & High quality (normal)\\ + \hline + $3$ & High quality with 3d primitives (not implemented yet)\\ + \hline + $4$ & No face drawing, direct bitmap drawing (low memory usage)\\ + \hline + $5$ & No color interpolation, direct bitmap drawing (low memory usage)\\ + \hline + $6$ & High quality, direct bitmap drawing (low memory usage)\\ + \hline + $7$ & High quality with 3d primitives, direct bitmap drawing (not implemented yet)\\ + \hline + $8$ & Draw dots instead of primitives (extremely fast)\\ + \hline + \end{tabular} + \end{center} +\item[\textbackslash{}mgltexon, \textbackslash{}mgltexoff] + To activate/deactivate the creation of MGL scripts and images. Notice these commands have local behavior in the sense that their effect is from the point they are called on. +\item[\textbackslash{}mglcomment, \textbackslash{}mglnocomment] + To make visible/invisible the contents of the \texttt{mglcomment} environments. These commands have local effect too. \item[\textbackslash{}mglTeX] - It just pretty prints the name of the package ''\mglTeX''. + It just pretty prints the name of the package ``\mglTeX''. \end{description} @@ -271,17 +342,17 @@ Finally, you can just show MGL script itself An example of usage of \texttt{\textbackslash{}mglplot} command would be: \begin{verbatim} -\begin{mglplotsettings} +\begin{mglsetup} box '@{W9}' : axis -\end{mglplotsettings} -\begin{mglplotsettings}[2d] +\end{mglsetup} +\begin{mglsetup}[2d] box : axis grid 'xy' ';k' -\end{mglplotsettings} -\begin{mglplotsettings}[3d] +\end{mglsetup} +\begin{mglsetup}[3d] rotate 50 60 box : axis : grid 'xyz' ';k' -\end{mglplotsettings} +\end{mglsetup} \begin{figure}[!ht] \centering \mglplot[scale=0.5]{new a 200 'sin(pi*x)':plot a '2B'} @@ -300,31 +371,31 @@ An example of usage of \texttt{\textbackslash{}mglplot} command would be: \end{figure} \end{verbatim} -\begin{mglplotsettings} +\begin{mglsetup} box '@{W9}' : axis -\end{mglplotsettings} -\begin{mglplotsettings}[2d] +\end{mglsetup} +\begin{mglsetup}[2d] box : axis grid 'xy' ';k' -\end{mglplotsettings} -\begin{mglplotsettings}[3d] +\end{mglsetup} +\begin{mglsetup}[3d] rotate 50 60 box : axis : grid 'xyz' ';k' -\end{mglplotsettings} +\end{mglsetup} \begin{figure}[!ht] \centering \mglplot[scale=0.5]{new a 200 'sin(pi*x)':plot a '2B'} \end{figure} \begin{figure}[!ht] \centering - \mglplot[scale=0.5,settings=2d]{ + \mglplot[scale=0.5,setup=2d]{ fplot 'sin(pi*x)' '2B' : fplot 'cos(pi*x^2)' '2R' } \end{figure} \begin{figure}[!ht] \centering - \mglplot[width=0.5 \textwidth, settings=3d] + \mglplot[width=0.5 \textwidth, setup=3d] {fsurf 'sin(pi*x)+cos(pi*y)'} \end{figure} @@ -334,7 +405,61 @@ As an additional feature, when an image is not found or cannot be included, inst \mglgraphics{xyz} \end{figure} -The last sample is displaying the content of the MGL file using \texttt{\textbackslash{}mglinclude} command: +Let's display the content of the MGL file using \texttt{\textbackslash{}mglinclude} command: \mglinclude{Vectorial} +The following commentary will be visible, since \mglTeX{} has been called with the \texttt{comments} option. +\begin{verbatim} + \begin{mglcomment} + This is a visible commentary + that can have multiple lines + \end{mglcomment} +\end{verbatim} +The result is: +\begin{mglcomment} + This is a visible commentary + that can have multiple lines +\end{mglcomment} + +The following commentary won't be visible, since it is wrapped by \texttt{\textbackslash{}mglnocomments} and \texttt{\textbackslash{}mglcomments}. +\begin{verbatim} + \mglnocomments + \begin{mglcomment} + This is an invisible commentary + that can have multiple lines + \end{mglcomment} + \mglcomments +\end{verbatim} +\mglnocomments +\begin{mglcomment} + This is an invisible commentary + that can have multiple lines +\end{mglcomment} +\mglcomments + +The last example is the use of the \texttt{\textbackslash{}mgltexon} and \texttt{\textbackslash{}mgltexoff} commands. For example, the following image won't be generated: +\begin{verbatim} + \mgltexoff + \begin{figure}[!ht] + \centering + \begin{mgl} + box : axis + fplot 'sin(pi*x)' '2B' + \end{mgl} + \end{figure} + \mgltexon +\end{verbatim} +The result is: +\mgltexoff +\begin{figure}[!ht] + \centering + \begin{mgl} + box : axis + fplot 'sin(pi*x)' '2B' + \end{mgl} +\end{figure} +\mgltexon + + + \end{document} \ No newline at end of file diff --git a/src/addon.cpp b/src/addon.cpp index f523bed..d1185f0 100644 --- a/src/addon.cpp +++ b/src/addon.cpp @@ -45,22 +45,16 @@ void MGL_EXPORT mgl_strcls(char *str) delete []tmp; } //----------------------------------------------------------------------------- -int MGL_EXPORT_PURE mgl_strpos(const char *str,char *fnd) +long MGL_EXPORT_PURE mgl_strpos(const char *str,char *fnd) { const char *p=strstr(str,fnd); - int res; - if(p) res = p-str; - else res = -1; - return res; + return p?p-str:-1L; } //----------------------------------------------------------------------------- -int MGL_EXPORT_PURE mgl_chrpos(const char *str,char ch) +long MGL_EXPORT_PURE mgl_chrpos(const char *str,char ch) { const char *p=str?strchr(str,ch):0; - int res; - if(p) res = p-str; - else res = -1; - return res; + return p?p-str:-1L; } //----------------------------------------------------------------------------- MGL_EXPORT char *mgl_fgetstr(FILE *fp) @@ -112,7 +106,7 @@ void MGL_EXPORT mgl_test(const char *str, ...) char buf[256]; va_list lst; va_start(lst,str); - vsnprintf(buf,256,str,lst); + vsnprintf(buf,256,str,lst); buf[255]=0; va_end(lst); printf("TEST: %s\n",buf); fflush(stdout); @@ -123,7 +117,7 @@ void MGL_EXPORT mgl_info(const char *str, ...) char buf[256]; va_list lst; va_start(lst,str); - vsnprintf(buf,256,str,lst); + vsnprintf(buf,256,str,lst); buf[255]=0; va_end(lst); printf("%s",buf); FILE *fp = fopen("info.txt","at"); diff --git a/src/axis.cpp b/src/axis.cpp index f9db21a..30bc089 100644 --- a/src/axis.cpp +++ b/src/axis.cpp @@ -856,9 +856,9 @@ void mglCanvas::Labelw(char dir, const wchar_t *text, mreal pos, const char *opt mglPnt &pp = Pnt[kk]; if(pp.u<0 || (pp.u==0 && pp.v<0)) { pp.u=-pp.u; pp.v=-pp.v; pp.w=-pp.w; } + ff[0] = GetLabelPos(t, kk, *aa); strcat(font,ff); + text_plot(kk,text,font,-1.4,0.35+shift); } - ff[0] = GetLabelPos(t, kk, *aa); strcat(font,ff); - text_plot(kk,text,font,-1.4,0.35+shift); } LoadState(); } diff --git a/src/base.cpp b/src/base.cpp index 06ce6a4..d54571d 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -24,7 +24,7 @@ char *mgl_strdup(const char *s) { char *r = (char *)malloc((strlen(s)+1)*sizeof(char)); - memcpy(r,s,(strlen(s)+1)*sizeof(char)); + if(r) memcpy(r,s,(strlen(s)+1)*sizeof(char)); return r; } //----------------------------------------------------------------------------- @@ -170,7 +170,7 @@ void mglBase::StartGroup(const char *name, int id) { LightScale(&B); char buf[128]; - snprintf(buf,128,"%s_%d",name,id); + snprintf(buf,128,"%s_%d",name,id); buf[127]=0; StartAutoGroup(buf); } //----------------------------------------------------------------------------- @@ -990,7 +990,7 @@ mreal mglBase::AddTexture(mglColor c) //----------------------------------------------------------------------------- mreal mglBase::NextColor(long &id) { - long i=abs(id)/256, n=Txt[i].n, p=abs(id)&0xff; + long i=labs(id)/256, n=Txt[i].n, p=labs(id)&0xff; if(id>=0) { p=(p+1)%n; id = 256*i+p; } CDef = i + (n>0 ? (p+0.5)/n : 0); CurrPal++; sprintf(last_style+11,"{&%g}",CDef); @@ -1001,7 +1001,7 @@ mreal mglBase::NextColor(long &id) //----------------------------------------------------------------------------- mreal mglBase::NextColor(long id, long sh) { - long i=abs(id)/256, n=Txt[i].n, p=abs(id)&0xff; + long i=labs(id)/256, n=Txt[i].n, p=labs(id)&0xff; if(id>=0) p=(p+sh)%n; mreal cc = i + (n>0 ? (p+0.5)/n : 0); sprintf(last_style+11,"{&%g}",cc); diff --git a/src/base_cf.cpp b/src/base_cf.cpp index 7f46bb9..98702b9 100644 --- a/src/base_cf.cpp +++ b/src/base_cf.cpp @@ -258,7 +258,7 @@ void MGL_EXPORT mgl_test_txt(const char *str, ...) char buf[256]; va_list lst; va_start(lst,str); - vsnprintf(buf,256,str,lst); + vsnprintf(buf,256,str,lst); buf[255]=0; va_end(lst); printf("TEST: %s\n",buf); fflush(stdout); diff --git a/src/canvas.cpp b/src/canvas.cpp index fd6e388..9d4099f 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -121,8 +121,7 @@ void mglCanvas::ClearFrame() Pnt.clear(); Prm.clear(); Ptx.clear(); Glf.clear(); ClearPrmInd(); Txt.clear(); Txt.reserve(3); mglTexture t1(MGL_DEF_PAL,-1), t2(MGL_DEF_SCH,1); - MGL_PUSH(Txt,t1,mutexTxt); - MGL_PUSH(Txt,t2,mutexTxt); + Txt.push_back(t1); Txt.push_back(t2); // No extra lock is required } #if MGL_HAVE_PTHREAD pthread_mutex_unlock(&mutexAct); @@ -800,6 +799,7 @@ std::wstring MGL_EXPORT mgl_ftoa(double v, const char *fmt) int fdig = int(log10(v)); fdig = fdig>0?(fdig "\cdot 10^{...}" { if(res[0]=='1' && (res[1]=='e' || res[1]=='E')) diff --git a/src/complex.cpp b/src/complex.cpp index 4bde0ee..3457c7d 100644 --- a/src/complex.cpp +++ b/src/complex.cpp @@ -97,28 +97,19 @@ MGL_NO_EXPORT void *mgl_csmth_x(void *par) long nx=t->p[0], kind=t->p[2]; dual *b=t->a; const dual *a=t->b; - if(kind==SMOOTH_LINE_3) + if(kind>0) #if !MGL_HAVE_PTHREAD #pragma omp parallel for #endif for(long i=t->id;in;i+=mglNumThr) { register long j = i%nx; - if(j>0 && jid;in;i+=mglNumThr) - { - register long j = i%nx; - if(j>1 && jnx-1) j = i+nx-1-j-kind; + else j=i; + for(long k=-kind;k<=kind;k++) b[i] += a[j+k]/mreal(2*kind+1); } - else if(kind==SMOOTH_QUAD_5) + else #if !MGL_HAVE_PTHREAD #pragma omp parallel for #endif @@ -137,28 +128,19 @@ MGL_NO_EXPORT void *mgl_csmth_y(void *par) long nx=t->p[0],ny=t->p[1], kind=t->p[2]; dual *b=t->a; const dual *a=t->b; - if(kind==SMOOTH_LINE_3) -#if !MGL_HAVE_PTHREAD -#pragma omp parallel for -#endif - for(long i=t->id;in;i+=mglNumThr) - { - register long j = (i/nx)%ny; - if(j>0 && j0) #if !MGL_HAVE_PTHREAD #pragma omp parallel for #endif for(long i=t->id;in;i+=mglNumThr) { register long j = (i/nx)%ny; - if(j>1 && jny-1) j = i+(ny-1-j-kind)*nx; + else j=i; + for(long k=-kind;k<=kind;k++) b[i] += a[j+k*nx]/mreal(2*kind+1); } - else if(kind==SMOOTH_QUAD_5) + else #if !MGL_HAVE_PTHREAD #pragma omp parallel for #endif @@ -177,28 +159,19 @@ MGL_NO_EXPORT void *mgl_csmth_z(void *par) register long nn=t->p[0]*t->p[1], nz=t->n/nn, kind=t->p[2]; dual *b=t->a; const dual *a=t->b; - if(kind==SMOOTH_LINE_3) + if(kind>0) #if !MGL_HAVE_PTHREAD #pragma omp parallel for #endif for(long i=t->id;in;i+=mglNumThr) { register long j = i/nn; - if(j>0 && jnz-1) j = i+(nz-1-j-kind)*nn; + else j=i; + for(long k=-kind;k<=kind;k++) b[i] += a[j+k*nn]/mreal(2*kind+1); } - else if(kind==SMOOTH_LINE_5) -#if !MGL_HAVE_PTHREAD -#pragma omp parallel for -#endif - for(long i=t->id;in;i+=mglNumThr) - { - register long j = i/nn; - if(j>1 && jnx,ny=d->ny,nz=d->nz; // if(Type == SMOOTH_NONE) return; long p[3]={nx,ny,Type}; @@ -1081,6 +1070,7 @@ void MGL_EXPORT mgl_difr_axial(dual *a,int n,int step,dual q,int Border,dual *tm //----------------------------------------------------------------------------- MGL_NO_EXPORT void *mgl_difr(void *par) { +#if !defined(_MSC_VER) // MSVC produce internal compiler error on this code mglThreadC *t=(mglThreadC *)par; long n=t->p[0], st=t->p[1], bord=t->p[3], nn=t->n; dual *b=t->a, q = *(t->b); @@ -1103,6 +1093,7 @@ MGL_NO_EXPORT void *mgl_difr(void *par) mgl_difr_grid(b + ((i%st)+n*(i/st)), n,st, q, bord,tmp,3); delete []tmp; } +#endif return 0; } void MGL_EXPORT mgl_datac_diffr(HADT d, const char *how, mreal q) diff --git a/src/complex_io.cpp b/src/complex_io.cpp index befe4c6..fa7f336 100644 --- a/src/complex_io.cpp +++ b/src/complex_io.cpp @@ -55,52 +55,87 @@ void mglFromStr(HADT d,char *buf,long NX,long NY,long NZ) // TODO: add multithre { if(NX<1 || NY <1 || NZ<1) return; mgl_datac_create(d, NX,NY,NZ); - long nb = strlen(buf); - register long i=0, j=0; const std::string loc = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); - while(j lines; + std::vector > numbs; + lines.push_back(buf); + for(char *s=buf; *s; s++) if(isn(*s)) + { lines.push_back(s+1); *s = 0; s++; } + numbs.resize(lines.size()); + long nl = long(lines.size()); +//#pragma omp parallel for + for(long k=0;k0 || buf[j+1]!='#') // this is columns id - while(j=nb) break; + while(b[j]=='#') // skip comment + { + if(i>0 || b[j+1]!='#') // this is columns id + while(j='a' && b[j]<='z') d->id.push_back(b[j]); + j++; + } + } + while(j' ' && ((b[j]!=',' && b[j]!=' ') || sk!=0) && b[j]!=';') + { + if(strchr("[{(",b[j])) sk++; + if(strchr("]})",b[j])) sk--; + j++; + } + b[j]=0; + double re=0,im=0; size_t ll=strlen(s); + while(s[ll]<=' ') ll--; + if(*s=='(') sscanf(s,"(%lg,%lg)",&re,&im); + else if(*s=='i') { re=0; im=atof(s+1); } + else if(*s=='[') sscanf(s,"[%lg,%lg]",&re,&im); + else if(*s=='{') sscanf(s,"{%lg,%lg}",&re,&im); + else if(s[ll]=='i') + { + double a,b; s[ll] = 0; + int s1=sscanf(s,"%lg+%lg",&re,&im); + int s2=sscanf(s,"%lg-%lg",&a,&b); + if(s1<2) + { + if(s2==2) { re=a; im=-b; } + else { im=atof(s); re=0; } + } + } else { - while(j='a' && buf[j]<='z') - d->id.push_back(buf[j]); - j++; + if(s2==2) { re=a; im=-b; } + else { re=atof(s); im=0; } } } - while(j=' ' && buf[j]!=';') j++; - buf[j]=0; - double re=0,im=0; size_t ll=strlen(s); - while(s[ll]<=' ') ll--; - if(*s=='(') sscanf(s,"(%lg,%lg)",&re,&im); - else if(*s=='[') sscanf(s,"[%lg,%lg]",&re,&im); - else if(*s=='{') sscanf(s,"{%lg,%lg}",&re,&im); - else if(s[ll]=='i') - { - double a,b; s[ll] = 0; - int s1=sscanf(s,"%lg+%lg",&re,&im); - int s2=sscanf(s,"%lg-%lg",&a,&b); - if(s2==2 && s1<2) { re=a; im=-b; } - + numbs[k].push_back(dual(re,im)); } - else - { - double a,b; - int s1=sscanf(s,"%lg+i%lg",&re,&im); - int s2=sscanf(s,"%lg-i%lg",&a,&b); - if(s2==2 && s1<2) { re=a; im=-b; } - } - d->a[i] = dual(re,im); - i++; if(i>=NX*NY*NZ) break; + } + register long i=0, n=NX*NY*NZ; + for(long k=0;k &vals = numbs[k]; + long c = vals.size(); + if(c>n-i) c = n-i; + memcpy(d->a+i,&(vals[0]),c*sizeof(dual)); + i += c; } setlocale(LC_NUMERIC, loc.c_str()); } @@ -243,7 +278,7 @@ void MGL_EXPORT mgl_datac_save_(uintptr_t *d, const char *fname,int *ns,int l) //----------------------------------------------------------------------------- int MGL_EXPORT mgl_datac_read(HADT d, const char *fname) { - long l=1,m=1,k=1; + long l=1,m=1,k=1,sk=0; long nb,i; gzFile fp = gzopen(fname,"r"); if(!fp) @@ -257,13 +292,15 @@ int MGL_EXPORT mgl_datac_read(HADT d, const char *fname) bool first=false; // space is not allowed delimiter for file with complex numbers register char ch; for(i=nb-1;i>=0;i--) if(buf[i]>' ') break; - buf[i+1]=0; nb = i; // remove tailing spaces + buf[i+1]=0; nb = i+1; // remove tailing spaces for(i=0;i' ' && !first) first=true; - if(first && (ch=='\t' || ch==';') && buf[i+1]!='\t') k++; // ',' is not valid delimiter for complex arrays + if(strchr("[{(",ch)) sk++; + if(strchr("]})",ch)) sk--; + if(first && buf[i+1]>' ' && (ch=='\t' || ch==';' || ((ch==' '||ch==',') && sk==0) )) k++; } first = false; for(i=0;is; d->s = L"u"; - mglDataV x(d->nx,d->ny,d->nz); x.Fill(0,1,'x'); x.s=L"x"; - mglDataV y(d->nx,d->ny,d->nz); y.Fill(0,1,'y'); y.s=L"y"; - mglDataV z(d->nx,d->ny,d->nz); z.Fill(0,1,'z'); z.s=L"z"; + mglDataV x(d->nx,d->ny,d->nz, 0,1,'x'); x.s=L"x"; + mglDataV y(d->nx,d->ny,d->nz, 0,1,'y'); y.s=L"y"; + mglDataV z(d->nx,d->ny,d->nz, 0,1,'z'); z.s=L"z"; + mglDataV i(d->nx,d->ny,d->nz, 0,d->nx-1,'x'); i.s=L"i"; + mglDataV j(d->nx,d->ny,d->nz, 0,d->ny-1,'y'); j.s=L"j"; + mglDataV k(d->nx,d->ny,d->nz, 0,d->nz-1,'z'); k.s=L"k"; mglDataV r(d->nx,d->ny,d->nz); r.s=L"#$mgl"; mglData v(vdat), w(wdat); v.s = L"v"; w.s = L"w"; std::vector list; list.push_back(&x); list.push_back(&y); list.push_back(&z); list.push_back(d); list.push_back(&v); list.push_back(&w); list.push_back(&r); + list.push_back(&i); list.push_back(&j); list.push_back(&k); d->Set(mglFormulaCalcC(eq,list)); d->s = s; } void MGL_EXPORT mgl_datac_modify_vw_(uintptr_t *d, const char *eq, uintptr_t *v, uintptr_t *w,int l) @@ -651,7 +692,7 @@ int MGL_EXPORT mgl_datac_read_range(HADT dat, const char *templ, double from, do char *fname = new char[n]; //read first file - do{ snprintf(fname,n,templ,t); t+= step; } while(!mgl_datac_read(&d,fname) && t<=to); + do{ snprintf(fname,n,templ,t); fname[n-1]=0; t+= step; } while(!mgl_datac_read(&d,fname) && t<=to); if(t>to) { delete []fname; return false; } kx = d.nx; ky = d.ny; kz = d.nz; @@ -661,7 +702,7 @@ int MGL_EXPORT mgl_datac_read_range(HADT dat, const char *templ, double from, do // read other files for(;t<=to;t+=step) { - snprintf(fname,n,templ,t); + snprintf(fname,n,templ,t); fname[n-1]=0; if(mgl_datac_read(&d,fname)) if(!mgl_add_file(kx,ky,kz,b,&d,as_slice)) { delete []fname; free(b); return false; } diff --git a/src/cont.cpp b/src/cont.cpp index e86454f..987c5d2 100644 --- a/src/cont.cpp +++ b/src/cont.cpp @@ -568,8 +568,8 @@ void MGL_EXPORT mgl_contf_gen(HMGL gr, mreal v1, mreal v2, HCDT a, HCDT x, HCDT // draw it bool b1d2 = a->v(i+1,j,ak)>v2 && a->v(i,j-1,ak)>v2; bool b2d1 = a->v(i,j,ak)>v2 && a->v(i+1,j-1,ak)>v2; - mreal vv = mgl_data_linear(a,i+0.5,j-0.5,ak); - vv = (vv-v1)*(vv-v2); +// mreal vv = mgl_data_linear(a,i+0.5,j-0.5,ak); +// vv = (vv-v1)*(vv-v2); if(num<3) continue; if(num==4) gr->quad_plot(p[0],p[1],p[3],p[2]); else if(num==3) gr->trig_plot(p[0],p[1],p[2]); diff --git a/src/data.cpp b/src/data.cpp index 14930d8..0ab7859 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -159,28 +159,19 @@ MGL_NO_EXPORT void *mgl_smth_x(void *par) long nx=t->p[0], kind=t->p[2]; mreal *b=t->a, delta=t->c[0]; const mreal *a=t->b; - if(kind==SMOOTH_LINE_3) + if(kind>0) #if !MGL_HAVE_PTHREAD #pragma omp parallel for #endif for(long i=t->id;in;i+=mglNumThr) { register long j = i%nx; - if(j>0 && jid;in;i+=mglNumThr) - { - register long j = i%nx; - if(j>1 && jnx-1) j = i+nx-1-j-kind; + else j=i; + for(long k=-kind;k<=kind;k++) b[i] += a[j+k]/(2*kind+1); } - else if(kind==SMOOTH_QUAD_5) + else #if !MGL_HAVE_PTHREAD #pragma omp parallel for #endif @@ -196,8 +187,11 @@ MGL_NO_EXPORT void *mgl_smth_x(void *par) #pragma omp parallel for #endif for(long i=t->id;in;i+=mglNumThr) - b[i] = mgl_max(a[i]-delta,mgl_min(a[i]+delta,b[i])); - return 0; + { + double ab = fabs(a[i]-b[i]); + if(ab>delta) b[i] = a[i]+(delta/ab)*(b[i]-a[i]); + } + return 0; } MGL_NO_EXPORT void *mgl_smth_y(void *par) { @@ -205,28 +199,19 @@ MGL_NO_EXPORT void *mgl_smth_y(void *par) long nx=t->p[0],ny=t->p[1], kind=t->p[2]; mreal *b=t->a, delta=t->c[0]; const mreal *a=t->b; - if(kind==SMOOTH_LINE_3) + if(kind>0) #if !MGL_HAVE_PTHREAD #pragma omp parallel for #endif for(long i=t->id;in;i+=mglNumThr) { register long j = (i/nx)%ny; - if(j>0 && jid;in;i+=mglNumThr) - { - register long j = (i/nx)%ny; - if(j>1 && jny-1) j = i+(ny-1-j-kind)*nx; + else j=i; + for(long k=-kind;k<=kind;k++) b[i] += a[j+k*nx]/(2*kind+1); } - else if(kind==SMOOTH_QUAD_5) + else #if !MGL_HAVE_PTHREAD #pragma omp parallel for #endif @@ -242,8 +227,11 @@ MGL_NO_EXPORT void *mgl_smth_y(void *par) #pragma omp parallel for #endif for(long i=t->id;in;i+=mglNumThr) - b[i] = mgl_max(a[i]-delta,mgl_min(a[i]+delta,b[i])); - return 0; + { + double ab = fabs(a[i]-b[i]); + if(ab>delta) b[i] = a[i]+(delta/ab)*(b[i]-a[i]); + } + return 0; } MGL_NO_EXPORT void *mgl_smth_z(void *par) { @@ -251,28 +239,19 @@ MGL_NO_EXPORT void *mgl_smth_z(void *par) register long nn=t->p[0]*t->p[1], nz=t->n/nn, kind=t->p[2]; mreal *b=t->a, delta=t->c[0]; const mreal *a=t->b; - if(kind==SMOOTH_LINE_3) + if(kind>1) #if !MGL_HAVE_PTHREAD #pragma omp parallel for #endif for(long i=t->id;in;i+=mglNumThr) { register long j = i/nn; - if(j>0 && jnz-1) j = i+(nz-1-j-kind)*nn; + else j=i; + for(long k=-kind;k<=kind;k++) b[i] += a[j+k*nn]/(2*kind+1); } - else if(kind==SMOOTH_LINE_5) -#if !MGL_HAVE_PTHREAD -#pragma omp parallel for -#endif - for(long i=t->id;in;i+=mglNumThr) - { - register long j = i/nn; - if(j>1 && jid;in;i+=mglNumThr) - b[i] = mgl_max(a[i]-delta,mgl_min(a[i]+delta,b[i])); + { + double ab = fabs(a[i]-b[i]); + if(ab>delta) b[i] = a[i]+(delta/ab)*(b[i]-a[i]); + } return 0; } void MGL_EXPORT mgl_data_smooth(HMDT d, const char *dirs, mreal delta) { - long Type = SMOOTH_QUAD_5; + long Type = -1; if(!dirs || *dirs==0) dirs = "xyz"; - if(strchr(dirs,'0') || strchr(dirs,'1')) return; - if(strchr(dirs,'3')) Type = SMOOTH_LINE_3; - if(strchr(dirs,'5')) Type = SMOOTH_LINE_5; + if(strchr(dirs,'0')) return; + if(strchr(dirs,'d')) + { + if(strchr(dirs,'1')) Type = 1; + if(strchr(dirs,'2')) Type = 2; + if(strchr(dirs,'3')) Type = 3; + if(strchr(dirs,'4')) Type = 4; + if(strchr(dirs,'5')) Type = 5; + if(strchr(dirs,'6')) Type = 6; + if(strchr(dirs,'7')) Type = 7; + if(strchr(dirs,'8')) Type = 8; + if(strchr(dirs,'9')) Type = 9; + } + else + { + if(strchr(dirs,'1')) return; + if(strchr(dirs,'3')) Type = 1; + if(strchr(dirs,'5')) Type = 2; + } long nx=d->nx,ny=d->ny,nz=d->nz; // if(Type == SMOOTH_NONE) return; long p[3]={nx,ny,Type}; @@ -1359,19 +1357,24 @@ MGL_EXPORT const char *mgl_data_info(HCDT d) // NOTE: Not thread safe function! { static char buf[512]; char s[128]; buf[0]=0; - snprintf(s,128,"nx = %ld\tny = %ld\tnz = %ld\n",d->GetNx(),d->GetNy(),d->GetNz()); strcat(buf,s); + snprintf(s,128,"nx = %ld\tny = %ld\tnz = %ld\n",d->GetNx(),d->GetNy(),d->GetNz()); + s[127]=0; strcat(buf,s); long i=0,j=0,k=0; mreal A=0,Wa=0,X=0,Y=0,Z=0,Wx=0,Wy=0,Wz=0, b; b = mgl_data_max_int(d,&i,&j,&k); - snprintf(s,128,"Maximum is %g\t at x = %ld\ty = %ld\tz = %ld\n", b,i,j,k); strcat(buf,s); + snprintf(s,128,"Maximum is %g\t at x = %ld\ty = %ld\tz = %ld\n", b,i,j,k); + s[127]=0; strcat(buf,s); b = mgl_data_min_int(d,&i,&j,&k); - snprintf(s,128,"Minimum is %g\t at x = %ld\ty = %ld\tz = %ld\n", b,i,j,k); strcat(buf,s); + snprintf(s,128,"Minimum is %g\t at x = %ld\ty = %ld\tz = %ld\n", b,i,j,k); + s[127]=0; strcat(buf,s); mgl_data_momentum_val(d,'a',&A,&Wa,0,0); mgl_data_momentum_val(d,'x',&X,&Wx,0,0); mgl_data_momentum_val(d,'y',&Y,&Wy,0,0); mgl_data_momentum_val(d,'z',&Z,&Wz,0,0); - snprintf(s,128,"Averages are:\n = %g\t = %g\t = %g\t = %g\n", A,X,Y,Z); strcat(buf,s); - snprintf(s,128,"Widths are:\nWa = %g\tWx = %g\tWy = %g\tWz = %g\n", Wa,Wx,Wy,Wz); strcat(buf,s); + snprintf(s,128,"Averages are:\n = %g\t = %g\t = %g\t = %g\n", A,X,Y,Z); + s[127]=0; strcat(buf,s); + snprintf(s,128,"Widths are:\nWa = %g\tWx = %g\tWy = %g\tWz = %g\n", Wa,Wx,Wy,Wz); + s[127]=0; strcat(buf,s); return buf; } int MGL_EXPORT mgl_data_info_(uintptr_t *d, char *out, int len) @@ -2028,7 +2031,7 @@ void MGL_EXPORT mgl_data_refill_xy(HMDT dat, HCDT xdat, HCDT ydat, HCDT vdat, mr xx1=mgl_max(xx1,0); xx2=mgl_min(xx2,nx-1); yy1=mgl_max(yy1,0); yy2=mgl_min(yy2,ny-1); if(xx1>xx2 || yy1>yy2) continue; - + mreal d1x = vx1-vx0, d1y = vy1-vy0; mreal d2x = vx2-vx0, d2y = vy2-vy0; mreal d3x = vx3+vx0-vx1-vx2, d3y = vy3+vy0-vy1-vy2; diff --git a/src/data_ex.cpp b/src/data_ex.cpp index 193b55d..4a39428 100644 --- a/src/data_ex.cpp +++ b/src/data_ex.cpp @@ -741,7 +741,7 @@ HMDT MGL_EXPORT mgl_data_hist(HCDT dat, long n, mreal v1, mreal v2, long nsub) mglData *b=new mglData(n); mreal v[2]={v1,v2}; long nx=dat->GetNx(), ny=dat->GetNy(), nz=dat->GetNz(); - long ns=abs(nsub)+1, p[5]={n,ns,nx,ny,nz}; + long ns=labs(nsub)+1, p[5]={n,ns,nx,ny,nz}; if(nsub==0) mglStartThread(mgl_hist_1,mgl_hist_p, nx*ny*nz, b->a,(const mreal *)dat,0,p,v); else mglStartThread(mgl_hist_2,mgl_hist_p, nx*ny*nz*ns*ns*ns, b->a,(const mreal *)dat,0,p,v); return b; @@ -754,7 +754,7 @@ HMDT MGL_EXPORT mgl_data_hist_w(HCDT dat, HCDT weight, long n, mreal v1, mreal v mreal v[2]={v1,v2}; long nx=dat->GetNx(), ny=dat->GetNy(), nz=dat->GetNz(); - long ns=abs(nsub)+1, p[5]={n,ns,nx,ny,nz}; + long ns=labs(nsub)+1, p[5]={n,ns,nx,ny,nz}; if(nsub==0) mglStartThread(mgl_hist_1,mgl_hist_p, nx*ny*nz, b->a,(const mreal *)dat,(const mreal *)weight,p,v); else mglStartThread(mgl_hist_2,mgl_hist_p, nx*ny*nz*ns*ns*ns, b->a,(const mreal *)dat,(const mreal *)weight,p,v); return b; diff --git a/src/data_gr.cpp b/src/data_gr.cpp index faf12e7..1afc630 100644 --- a/src/data_gr.cpp +++ b/src/data_gr.cpp @@ -64,11 +64,15 @@ void MGL_EXPORT mgl_data_fill_eq(HMGL gr, HMDT d, const char *eq, HCDT vdat, HCD mglDataV x(d->nx,d->ny,d->nz, gr->Min.x,gr->Max.x,'x'); x.s=L"x"; mglDataV y(d->nx,d->ny,d->nz, gr->Min.y,gr->Max.y,'y'); y.s=L"y"; mglDataV z(d->nx,d->ny,d->nz, gr->Min.z,gr->Max.z,'z'); z.s=L"z"; + mglDataV i(d->nx,d->ny,d->nz, 0,d->nx-1,'x'); i.s=L"i"; + mglDataV j(d->nx,d->ny,d->nz, 0,d->ny-1,'y'); j.s=L"j"; + mglDataV k(d->nx,d->ny,d->nz, 0,d->nz-1,'z'); k.s=L"k"; mglDataV r(d->nx,d->ny,d->nz); r.s=L"#$mgl"; mglData v(vdat), w(wdat); v.s = L"v"; w.s = L"w"; std::vector list; list.push_back(&x); list.push_back(&y); list.push_back(&z); list.push_back(&r); list.push_back(d); list.push_back(&v); list.push_back(&w); + list.push_back(&i); list.push_back(&j); list.push_back(&k); d->Set(mglFormulaCalc(eq,list)); d->s = s; gr->LoadState(); } @@ -86,11 +90,15 @@ void MGL_EXPORT mgl_datac_fill_eq(HMGL gr, HADT d, const char *eq, HCDT vdat, HC mglDataV x(d->nx,d->ny,d->nz, gr->Min.x,gr->Max.x,'x'); x.s=L"x"; mglDataV y(d->nx,d->ny,d->nz, gr->Min.y,gr->Max.y,'y'); y.s=L"y"; mglDataV z(d->nx,d->ny,d->nz, gr->Min.z,gr->Max.z,'z'); z.s=L"z"; + mglDataV i(d->nx,d->ny,d->nz, 0,d->nx-1,'x'); i.s=L"i"; + mglDataV j(d->nx,d->ny,d->nz, 0,d->ny-1,'y'); j.s=L"j"; + mglDataV k(d->nx,d->ny,d->nz, 0,d->nz-1,'z'); k.s=L"k"; mglDataV r(d->nx,d->ny,d->nz); r.s=L"#$mgl"; mglData v(vdat), w(wdat); v.s = L"v"; w.s = L"w"; std::vector list; list.push_back(&x); list.push_back(&y); list.push_back(&z); list.push_back(&r); list.push_back(d); list.push_back(&v); list.push_back(&w); + list.push_back(&i); list.push_back(&j); list.push_back(&k); d->Set(mglFormulaCalcC(eq,list)); d->s = s; gr->LoadState(); } diff --git a/src/data_io.cpp b/src/data_io.cpp index 9cc098f..f1a4439 100644 --- a/src/data_io.cpp +++ b/src/data_io.cpp @@ -57,36 +57,57 @@ uintptr_t MGL_EXPORT mgl_create_data_file_(const char *fname,int l) void MGL_EXPORT mgl_delete_data_(uintptr_t *d) { if(_DT_) delete _DT_; } //----------------------------------------------------------------------------- -void mglFromStr(HMDT d,char *buf,long NX,long NY,long NZ) // TODO: add multithreading read +void mglFromStr(HMDT d,char *buf,long NX,long NY,long NZ) { if(NX<1 || NY <1 || NZ<1) return; mgl_data_create(d, NX,NY,NZ); - long nb = strlen(buf); - register long i=0, j=0; const std::string loc = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); - while(j lines; + std::vector > numbs; + lines.push_back(buf); + for(char *s=buf; *s; s++) if(isn(*s)) + { lines.push_back(s+1); *s = 0; s++; } + numbs.resize(lines.size()); + long nl = long(lines.size()); +#pragma omp parallel for + for(long k=0;k0 || buf[j+1]!='#') // this is columns id - while(j=nb) break; + while(b[j]=='#') // skip comment { - while(j0 || b[j+1]!='#') // this is columns id + while(j='a' && buf[j]<='z') - d->id.push_back(buf[j]); - j++; + while(j='a' && b[j]<='z') + d->id.push_back(b[j]); + j++; + } } + while(j' ' && b[j]!=',' && b[j]!=';') j++; + b[j]=0; + numbs[k].push_back(strstr(s,"NAN")?NAN:atof(s)); } - char *s=buf+j; - while(j' ' && buf[j]!=',' && buf[j]!=';') j++; - buf[j]=0; - d->a[i] = strstr(s,"NAN")?NAN:atof(s); - i++; if(i>=NX*NY*NZ) break; + } + register long i=0, n=NX*NY*NZ; + for(long k=0;k &vals = numbs[k]; + long c = vals.size(); + if(c>n-i) c = n-i; + memcpy(d->a+i,&(vals[0]),c*sizeof(mreal)); + i += c; } setlocale(LC_NUMERIC, loc.c_str()); } @@ -329,7 +350,7 @@ int MGL_EXPORT mgl_data_read(HMDT d, const char *fname) bool first=false; register char ch; for(i=nb-1;i>=0;i--) if(buf[i]>' ') break; - buf[i+1]=0; nb = i; // remove tailing spaces + buf[i+1]=0; nb = i+1; // remove tailing spaces for(i=0;inx,d->ny,d->nz, 0,1,'x'); x.s=L"x"; mglDataV y(d->nx,d->ny,d->nz, 0,1,'y'); y.s=L"y"; mglDataV z(d->nx,d->ny,d->nz, 0,1,'z'); z.s=L"z"; + mglDataV i(d->nx,d->ny,d->nz, 0,d->nx-1,'x'); i.s=L"i"; + mglDataV j(d->nx,d->ny,d->nz, 0,d->ny-1,'y'); j.s=L"j"; + mglDataV k(d->nx,d->ny,d->nz, 0,d->nz-1,'z'); k.s=L"k"; mglDataV r(d->nx,d->ny,d->nz); r.s=L"#$mgl"; mglData v(vdat), w(wdat); v.s = L"v"; w.s = L"w"; std::vector list; list.push_back(&x); list.push_back(&y); list.push_back(&z); list.push_back(d); list.push_back(&v); list.push_back(&w); list.push_back(&r); + list.push_back(&i); list.push_back(&j); list.push_back(&k); d->Set(mglFormulaCalc(eq,list)); d->s = s; } void MGL_EXPORT mgl_data_modify_vw_(uintptr_t *d, const char *eq, uintptr_t *v, uintptr_t *w,int l) @@ -1075,7 +1100,7 @@ int MGL_EXPORT mgl_data_read_range(HMDT dat, const char *templ, double from, dou char *fname = new char[n]; //read first file - do{ snprintf(fname,n,templ,t); t+= step; } while(!mgl_data_read(&d,fname) && t<=to); + do{ snprintf(fname,n,templ,t); fname[n-1]=0; t+= step; } while(!mgl_data_read(&d,fname) && t<=to); if(t>to) { delete []fname; return false; } kx = d.nx; ky = d.ny; kz = d.nz; @@ -1085,7 +1110,7 @@ int MGL_EXPORT mgl_data_read_range(HMDT dat, const char *templ, double from, dou // read other files for(;t<=to;t+=step) { - snprintf(fname,n,templ,t); + snprintf(fname,n,templ,t); fname[n-1]=0; if(mgl_data_read(&d,fname)) if(!mgl_add_file(kx,ky,kz,b,&d,as_slice)) { delete []fname; free(b); return false; } diff --git a/src/data_png.cpp b/src/data_png.cpp index 0af84ae..2773487 100644 --- a/src/data_png.cpp +++ b/src/data_png.cpp @@ -27,8 +27,8 @@ //----------------------------------------------------------------------------- size_t MGL_LOCAL_PURE mgl_col_dif(unsigned char *c1,unsigned char *c2,bool sum) { - size_t res,d1=abs(long(c1[0])-long(c2[0])), - d2=abs(long(c1[1])-long(c2[1])),d3=abs(long(c1[2])-long(c2[2])); + size_t res,d1=labs(long(c1[0])-long(c2[0])), + d2=labs(long(c1[1])-long(c2[1])),d3=labs(long(c1[2])-long(c2[2])); if(sum) res = d1+d2+d3; else res = mgl_max(d1,mgl_max(d2,d3)); return res; @@ -232,6 +232,7 @@ void MGL_EXPORT mgl_data_export(HCDT dd, const char *fname, const char *scheme,m if(!strcmp(fname+len-4,".bmp")) mgl_bmp_save(fname, nx,ny,p); if(!strcmp(fname+len-4,".png")) mgl_png_save(fname, nx,ny,p); if(!strcmp(fname+len-4,".eps") || !strcmp(fname+len-4,".bps")) mgl_bps_save(fname, nx,ny,p); + delete []p; delete []d; } //----------------------------------------------------------------------------- void MGL_EXPORT mgl_data_export_(uintptr_t *d, const char *fname, const char *scheme,mreal *v1,mreal *v2,int *ns,int l,int n) diff --git a/src/evalp.cpp b/src/evalp.cpp index 5b4489f..0455716 100644 --- a/src/evalp.cpp +++ b/src/evalp.cpp @@ -19,6 +19,7 @@ ***************************************************************************/ #include #include +#include "mgl2/base.h" #include "mgl2/parser.h" #if MGL_HAVE_GSL #include @@ -324,7 +325,7 @@ mglData MGL_NO_EXPORT mglFormulaCalc(std::wstring str, mglParser *arg, const std else if(!str.compare(L":")) res.a[0] = -1; else { - HCDT v=FindVar(head, L"#$mgl"); + v=FindVar(head, L"#$mgl"); if(v) res.Create(v->GetNx(),v->GetNy(),v->GetNz()); if(!str.compare(L"rnd")) for(long i=0;icurGr) + { + if(res.GetNN()==1) res.Create(100); + res.Fill(arg->curGr->Min.x, arg->curGr->Max.x,'x'); + } + else if(!str.compare(L"y") && arg && arg->curGr) + { + if(res.GetNN()==1) res.Create(100); + res.Fill(arg->curGr->Min.x, arg->curGr->Max.x,res.ny>1?'y':'x'); + } + else if(!str.compare(L"z") && arg && arg->curGr) + { + if(res.GetNN()==1) res.Create(100); + res.Fill(arg->curGr->Min.x, arg->curGr->Max.x,res.nz>1?'z':'x'); + }*/ else res = wcstod(str.c_str(),0); // this is number } return res; @@ -811,7 +828,7 @@ mglDataC MGL_NO_EXPORT mglFormulaCalcC(std::wstring str, mglParser *arg, const s else if(!str.compare(L":")) res.a[0] = -1; else { - HCDT v=FindVar(head, L"#$mgl"); + v=FindVar(head, L"#$mgl"); if(v) res.Create(v->GetNx(),v->GetNy(),v->GetNz()); if(!str.compare(L"rnd")) for(long i=0;icurGr) + res.Fill(arg->curGr->Min.x, arg->curGr->Max.x,'x'); + else if(!str.compare(L"y") && arg && arg->curGr) + res.Fill(arg->curGr->Min.x, arg->curGr->Max.x,res.ny>1?'y':'x'); + else if(!str.compare(L"z") && arg && arg->curGr) + res.Fill(arg->curGr->Min.x, arg->curGr->Max.x,res.nz>1?'z':'x');*/ else if(str[0]=='i') // this is imaginary number res = dual(0,(str.length()>1 && str[1]>' ')?wcstod(str.c_str(),0):1); else res = mreal(wcstod(str.c_str(),0)); // this is real number diff --git a/src/exec.cpp b/src/exec.cpp index ed776dc..e91e1ac 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -1149,11 +1149,25 @@ int MGL_NO_EXPORT mgls_read(mglGraph *gr, long , mglArg *a, const char *k, const int res=0; bool rr=true; mglData *d = dynamic_cast(a[0].d); + mglData *f = dynamic_cast(a[1].d); if(!d) return 1; - if(!strcmp(k,"ds")) rr=d->Read(a[1].s.c_str()); - else if(!strcmp(k,"dsn")) rr=d->Read(a[1].s.c_str(), iint(a[2].v)); - else if(!strcmp(k,"dsnn")) rr=d->Read(a[1].s.c_str(), iint(a[2].v),iint(a[3].v)); - else if(!strcmp(k,"dsnnn")) rr=d->Read(a[1].s.c_str(), iint(a[2].v),iint(a[3].v),iint(a[4].v)); + mglDataC c; + if(!strcmp(k,"ds")) + { rr=c.Read(a[1].s.c_str()); *d = c.Real(); } + else if(!strcmp(k,"dsn")) + { rr=c.Read(a[1].s.c_str(), iint(a[2].v)); *d = c.Real(); } + else if(!strcmp(k,"dsnn")) + { rr=c.Read(a[1].s.c_str(), iint(a[2].v),iint(a[3].v)); *d = c.Real(); } + else if(!strcmp(k,"dsnnn")) + { rr=c.Read(a[1].s.c_str(), iint(a[2].v),iint(a[3].v),iint(a[4].v)); *d = c.Real(); } + if(!strcmp(k,"dds") && f) + { rr=c.Read(a[2].s.c_str()); *d = c.Real(); *f = c.Imag(); } + if(!strcmp(k,"ddsn") && f) + { rr=c.Read(a[2].s.c_str(), iint(a[3].v)); *d = c.Real(); *f = c.Imag(); } + if(!strcmp(k,"ddsnn") && f) + { rr=c.Read(a[2].s.c_str(), iint(a[3].v),iint(a[4].v)); *d = c.Real(); *f = c.Imag(); } + if(!strcmp(k,"ddsnnn") && f) + { rr=c.Read(a[2].s.c_str(), iint(a[3].v),iint(a[4].v),iint(a[5].v)); *d = c.Real(); *f = c.Imag(); } if(!rr) gr->SetWarn(mglWarnFile,"Read"); return res; } @@ -2073,7 +2087,7 @@ int MGL_NO_EXPORT mgls_info(mglGraph *gr, long , mglArg *a, const char *k, const if(!strcmp(k,"d")) gr->SetWarn(-1,a[0].d->PrintInfo()); else if(!strcmp(k,"s")) gr->SetWarn(-1,a[0].s.c_str()); else if(!strcmp(k,"n")) - { char buf[128]; snprintf(buf,128,"value = %g",a[0].v); gr->SetWarn(-1,buf); } + { char buf[128]; snprintf(buf,128,"value = %g",a[0].v); buf[127]=0; gr->SetWarn(-1,buf); } else res = 1; return res; } //----------------------------------------------------------------------------- @@ -2455,7 +2469,7 @@ int MGL_NO_EXPORT mgls_fgets(mglGraph *gr, long , mglArg *a, const char *k, cons memset(buf,0,1024); if(!fgets(buf,1024,fp)) { - char b[32]; snprintf(b,32,"%d",n); + char b[32]; snprintf(b,32,"%d",n); b[31]=0; gr->SetWarn(mglWarnOpen,(a[2].s+" - line "+b).c_str()); fclose(fp); return res; } @@ -2475,7 +2489,7 @@ int MGL_NO_EXPORT mgls_fgets(mglGraph *gr, long , mglArg *a, const char *k, cons memset(buf,0,1024); if(!fgets(buf,1024,fp)) { - char b[32]; snprintf(b,32,"%d",n); + char b[32]; snprintf(b,32,"%d",n); b[31]=0; gr->SetWarn(mglWarnOpen,(a[3].s+" - line "+b).c_str()); fclose(fp); return res; } @@ -3075,7 +3089,7 @@ mglCommand mgls_base_cmd[] = { {"ranges","Set axis ranges","ranges x1 x2 y1 y2 [z1 z2]", mgls_ranges ,14}, {"rasterize","Rasterize and save to background","rasterize", mgls_rasterize ,12}, {"ray","Solve Hamiltonian ODE (find GO ray or trajectory)","ray Res 'ham' x0 y0 z0 px0 py0 pz0 [dz=0.1 tmax=10]", mgls_ray ,4}, - {"read","Read data from file","read Dat 'file' [nx ny nz]", mgls_read ,4}, + {"read","Read data from file","read Dat 'file' [nx ny nz] | ReDat ImDat 'file' [nx ny nz]", mgls_read ,4}, {"readall","Read and join data from several files","readall Dat 'templ' [slice]", mgls_readall ,4}, {"readhdf","Read data from HDF5 file","readhdf Dat 'file' 'id'", mgls_readhdf ,4}, {"readmat","Read data from file with sizes specified in first row","readmat Dat 'file' [dim]", mgls_readmat ,4}, diff --git a/src/export.cpp b/src/export.cpp index 65529b4..eac9c49 100644 --- a/src/export.cpp +++ b/src/export.cpp @@ -203,7 +203,7 @@ void MGL_NO_EXPORT mgl_printf(void *fp, bool gz, const char *str, ...) // NOTE T static char buf[1024]; va_list lst; va_start(lst,str); - vsnprintf(buf,1023,str,lst); + vsnprintf(buf,1023,str,lst); buf[1023]=0; va_end(lst); if(gz) gzprintf((gzFile)fp, "%s", buf); else fprintf((FILE *)fp, "%s", buf); @@ -214,7 +214,7 @@ std::string MGL_NO_EXPORT mgl_sprintf(const char *str, ...) char *buf=new char[1024]; va_list lst; va_start(lst,str); - vsnprintf(buf,1023,str,lst); + vsnprintf(buf,1023,str,lst); buf[1023]=0; va_end(lst); std::string res = buf; delete []buf; return res; @@ -223,7 +223,6 @@ std::string MGL_NO_EXPORT mgl_sprintf(const char *str, ...) int MGL_NO_EXPORT mgl_bps_save(const char *fname, int w, int h, unsigned char **p) { time_t now; time(&now); - register long i,j; bool gz = fname[strlen(fname)-1]=='z'; void *fp; @@ -242,7 +241,7 @@ int MGL_NO_EXPORT mgl_bps_save(const char *fname, int w, int h, unsigned char ** if(pos) { buf[pos]=buf[pos+1]='b'; buf[pos+2]=0; } FILE *fb = fopen(buf,"w"); fprintf(fb, "%%%%BoundingBox: 0 0 %d %d\n", w, h); - fclose(fb); + fclose(fb); delete []buf; } } mgl_printf(fp, gz, "%%!PS-Adobe-3.0 EPSF-3.0\n%%%%BoundingBox: 0 0 %d %d\n",w,h); @@ -577,7 +576,7 @@ void MGL_EXPORT mgl_write_frame(HMGL gr, const char *fname,const char *descr) { char buf[64]; if(!fname || !fname[0]) - { snprintf(buf,64,"%s%04d.jpg",_Gr_->PlotId.c_str(),_Gr_->GetNumFrame()); fname = buf; } + { snprintf(buf,64,"%s%04d.jpg",_Gr_->PlotId.c_str(),_Gr_->GetNumFrame()); buf[63]=0; fname = buf; } int len=strlen(fname); if(!strcmp(fname+len-4,".jpg")) mgl_write_jpg(gr,fname,descr); if(!strcmp(fname+len-5,".jpeg")) mgl_write_jpg(gr,fname,descr); @@ -618,14 +617,14 @@ void MGL_EXPORT mgl_write_frame_(uintptr_t *gr, const char *fname,const char *de void MGL_EXPORT mgl_show_image(HMGL gr, const char *viewer, int keep) { char fname[128], *cmd = new char [128]; - snprintf(fname,128,"%s.png", tmpnam(NULL)); + snprintf(fname,128,"%s.png", tmpnam(NULL)); fname[127]=0; mgl_write_png_solid(gr,fname,"MathGL ShowImage file"); if(!viewer || !viewer[0]) viewer = MGL_DEF_VIEWER; #ifdef WIN32 if(keep) { - snprintf(cmd,128,"%s %s &", viewer,fname); + snprintf(cmd,128,"%s %s &", viewer,fname); cmd[127]=0; if(system(cmd)==-1) printf("Error to call external viewer\n"); Sleep(2000); snprintf(cmd,128,"del %s", fname); @@ -634,13 +633,14 @@ void MGL_EXPORT mgl_show_image(HMGL gr, const char *viewer, int keep) #else if(keep) { - snprintf(cmd,128,"%s %s &", viewer,fname); + snprintf(cmd,128,"%s %s &", viewer,fname); cmd[127]=0; if(system(cmd)==-1) printf("Error to call external viewer\n"); sleep(2); snprintf(cmd,128,"rm %s", fname); } else snprintf(cmd,128,"%s %s; rm %s", viewer,fname,fname); #endif + cmd[127] = 0; if(system(cmd)==-1) printf("Error to call external viewer\n"); delete []cmd; } diff --git a/src/export_2d.cpp b/src/export_2d.cpp index 172d8a8..01a9b94 100644 --- a/src/export_2d.cpp +++ b/src/export_2d.cpp @@ -43,11 +43,11 @@ MGL_NO_EXPORT const char *mgl_get_dash(unsigned short d, mreal w,char dlm) if(((d>>j)&1) == p) f++; else { - snprintf(b,32," %g%c",f*w,dlm); s += b; + snprintf(b,32," %g%c",f*w,dlm); b[31]=0; s += b; p = (d>>j)&1; f = 1; n++; } } - snprintf(b,32,"%g",f*w); s += b; + snprintf(b,32,"%g",f*w); b[31]=0; s += b; s += (n%2) ? "" : " 0"; return s.c_str(); } @@ -193,7 +193,7 @@ void MGL_EXPORT mgl_write_eps(HMGL gr, const char *fname,const char *descr) if(pos) { buf[pos]=buf[pos+1]='b'; buf[pos+2]=0; } FILE *fb = fopen(buf,"w"); fprintf(fb, "%%%%BoundingBox: 0 0 %d %d\n", w, h); - fclose(fb); + fclose(fb); delete []buf; } const std::string loc = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); @@ -288,13 +288,14 @@ void MGL_EXPORT mgl_write_eps(HMGL gr, const char *fname,const char *descr) if(q.type<0) continue; // q.n1>=0 always cp.c = _Gr_->GetPrmCol(i); const mglPnt p1 = gr->GetPnt(q.n1); - if(q.type>1) snprintf(str,256,"%.2g %.2g %.2g rgb ", cp.r[0]/255.,cp.r[1]/255.,cp.r[2]/255.); + if(q.type>1) + { snprintf(str,256,"%.2g %.2g %.2g rgb ", cp.r[0]/255.,cp.r[1]/255.,cp.r[2]/255.); str[255]=0; } if(q.type==0) // mark { mreal x0 = p1.x,y0 = p1.y; snprintf(str,256,"%.2g lw %.2g %.2g %.2g rgb ", 50*q.s*q.w>1?50*q.s*q.w:1, cp.r[0]/255.,cp.r[1]/255.,cp.r[2]/255.); - wp=1; // NOTE: this may renew line style if a mark inside! + str[255]=0; wp=1; // NOTE: this may renew line style if a mark inside! if(q.s!=qs_old) { mgl_printf(fp, gz, "/ss {%g} def\n",q.s); @@ -341,7 +342,7 @@ void MGL_EXPORT mgl_write_eps(HMGL gr, const char *fname,const char *descr) else if(q.type==1) // line { snprintf(str,256,"%.2g lw %.2g %.2g %.2g rgb ", q.w>1 ? q.w:1., cp.r[0]/255.,cp.r[1]/255.,cp.r[2]/255.); - wp = q.w>1 ? q.w:1; st = q.n3; + str[255]=0; wp = q.w>1 ? q.w:1; st = q.n3; put_line(gr,fp,gz,i,wp,cp.c,st, "np %g %g mt ", "%g %g ll ", false, 1); const char *sd = mgl_get_dash(q.n3,q.w,' '); if(sd && sd[0]) mgl_printf(fp, gz, "%s [%s] %g sd dr\n",str,sd,q.w*q.s); @@ -610,7 +611,7 @@ void MGL_EXPORT mgl_write_tex(HMGL gr, const char *fname,const char *descr) const mglPrim &q = gr->GetPrm(i); if(q.type<0) continue; // q.n1>=0 always cp.c = _Gr_->GetPrmCol(i); - snprintf(cname,128,"color={rgb,255:red,%d;green,%d;blue,%d}",cp.r[0],cp.r[1],cp.r[2]); + snprintf(cname,128,"color={rgb,255:red,%d;green,%d;blue,%d}",cp.r[0],cp.r[1],cp.r[2]); cname[127]=0; const mglPnt p1=gr->GetPnt(q.n1); mreal x=p1.x/100,y=p1.y/100,s=q.s/100; diff --git a/src/export_3d.cpp b/src/export_3d.cpp index eee798e..5c9232a 100644 --- a/src/export_3d.cpp +++ b/src/export_3d.cpp @@ -92,9 +92,9 @@ void MGL_EXPORT mgl_obj_glyph_old(HMGL gr, const mglPrim &q, const mglPnt &p, FI } else // glyph_wire(p,f,g, d); { + long il=0; for(long ik=0;ikid;in;i+=mglNumThr) mgl_fft(t->b+2*(i%nx)+2*nx*ny*(i/nx), nx, ny, t->v, w, t->p[3]); @@ -184,7 +184,7 @@ MGL_NO_EXPORT void* mgl_fftz(void *par) #pragma omp parallel #endif { - void *w = mgl_fft_alloc_thr(nx); + void *w = mgl_fft_alloc_thr(nz); #pragma omp for nowait for(long i=t->id;in;i+=mglNumThr) mgl_fft(t->b+2*i, nx*ny, nz, t->v, w, t->p[3]); @@ -1071,26 +1071,28 @@ void MGL_EXPORT mgl_data_hankel_(uintptr_t *d, const char *dir,int l) void MGL_EXPORT mgl_data_fill_sample(HMDT d, const char *how) { if(!how || *how==0) return; - bool xx = strchr(how,'x'); - long n=d->nx; + bool kk = strchr(how,'k'); + long n=d->nx,dn=1; mreal *aa=d->a; + if(strchr(how,'y')) { n=d->ny; dn=d->nx; } + if(strchr(how,'z')) { n=d->nz; dn=d->nx*d->ny; } if(strchr(how,'h')) // Hankel { #if MGL_HAVE_GSL gsl_dht *dht = gsl_dht_new(n,0,1); #pragma omp parallel for for(long i=0;iny*d->nz;i++) memcpy(aa+i*n,aa,n*sizeof(mreal)); + for(long i=0;iGetNN();i++) aa[i] = aa[((i%(n*dn))/dn)*dn]; } void MGL_EXPORT mgl_data_fill_sample_(uintptr_t *d, const char *how,int l) { char *s=new char[l+1]; memcpy(s,how,l); s[l]=0; @@ -1257,7 +1259,7 @@ MGL_NO_EXPORT double *mgl_d_correl(HCDT d1, HCDT d2, const char *dir) { mgl_fft_data.wtz = wt; clear = false; mgl_fft_data.wnz=nz; } } if(clear) mgl_fft_free(wt,0,0); - return a; + delete []b; return a; } //----------------------------------------------------------------------------- HADT MGL_EXPORT mgl_datac_correl(HCDT d1, HCDT d2, const char *dir) diff --git a/src/fit.cpp b/src/fit.cpp index d49f686..4a78964 100644 --- a/src/fit.cpp +++ b/src/fit.cpp @@ -42,8 +42,8 @@ void MGL_EXPORT mgl_puts_fit(HMGL gr, double x, double y, double z, const char * long n = strlen(mglFitRes)+(pre?strlen(pre):0)+1; char *buf = new char[n]; if(pre) snprintf(buf,n,"%s%s",pre,mglFitRes); - else strcpy(buf,mglFitRes); - mgl_puts(gr,x,y,z,buf,font,size); + else strncpy(buf,mglFitRes,n); + buf[n-1]=0; mgl_puts(gr,x,y,z,buf,font,size); delete []buf; } void MGL_EXPORT mgl_puts_fit_(uintptr_t* gr, mreal *x, mreal *y, mreal *z, const char *prefix, const char *font, mreal *size, int l, int n) @@ -204,12 +204,12 @@ void mglPrepareFitEq(mglBase *gr,mreal chi, const char *eq, const char *var, mre { char buf[32]=""; mglFitChi = chi; - snprintf(mglFitRes,1024,"chi=%g",chi); + snprintf(mglFitRes,1024,"chi=%g",chi); mglFitRes[1023]=0; size_t i,k,len=strlen(var); for(i=0;iSetWarn(-1,mglFitRes); @@ -221,7 +221,7 @@ void mglPrepareFitEq(mglBase *gr,mreal chi, const char *eq, const char *var, mre if(c && (i==0 || !isalnum(eq[i-1])) && (i==len-1 || !isalnum(eq[i+1]))) { snprintf(buf,32,"%g",par[c-var]); - strcat(mglFitRes+k, buf); k+=strlen(buf); + buf[31]=0; strcat(mglFitRes+k, buf); k+=strlen(buf); } else { mglFitRes[k] = eq[i]; k++; } } diff --git a/src/font.cpp b/src/font.cpp index 6ea1871..d1b1318 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -688,7 +688,7 @@ bool mglFont::Load(const char *base, const char *path) } Clear(); // first clear old - snprintf(str,256,"%s%c%s.vfm",path,sep,base?base:""); + snprintf(str,256,"%s%c%s.vfm",path,sep,base?base:""); str[255]=0; std::vector norm, bold, ital, both; if(!(base && *base) || !read_main(str,norm)) { @@ -703,17 +703,17 @@ bool mglFont::Load(const char *base, const char *path) //================== bold =========================================== #pragma omp section { char str[256]; snprintf(str,256,"%s%c%s_b.vfm",path,sep,base); // this file may absent - read_data(str, 1, bold, ex_b); } + str[255]=0; read_data(str, 1, bold, ex_b); } //================== italic ========================================= #pragma omp section { char str[256]; snprintf(str,256,"%s%c%s_i.vfm",path,sep,base); - read_data(str, 2, ital, ex_i); } + str[255]=0; read_data(str, 2, ital, ex_i); } //================== bold-italic ==================================== #pragma omp section { char str[256]; snprintf(str,256,"%s%c%s_bi.vfm",path,sep,base); - read_data(str, 3, both, ex_bi); } + str[255]=0; read_data(str, 3, both, ex_bi); } } // now collect data diff --git a/src/interp.hpp b/src/interp.hpp index 0457157..46eee6d 100644 --- a/src/interp.hpp +++ b/src/interp.hpp @@ -250,5 +250,6 @@ template void mgl_gspline_init(long n, const mreal *x, const Treal c[5*i+3] = (3*h2)*(v[i+1]-v[i]) - (b[i+1]+b[i]+b[i])*h; c[5*i+4] = (2*h2*h)*(v[i]-v[i+1]) + (b[i+1]+b[i])*h2; } + delete []a; delete []b; } //----------------------------------------------------------------------------- diff --git a/src/opengl.cpp b/src/opengl.cpp index e35b6ca..0c327e0 100644 --- a/src/opengl.cpp +++ b/src/opengl.cpp @@ -17,7 +17,7 @@ HMGL MGL_EXPORT mgl_create_graph_gl() uintptr_t MGL_EXPORT mgl_create_graph_gl_() { return uintptr_t(new mglCanvasGL); } //----------------------------------------------------------------------------- -mglCanvasGL::mglCanvasGL() : mglCanvas(1,1) {} +mglCanvasGL::mglCanvasGL() : mglCanvas(1,1) { Clf(); Zoom(0,0,1,1); } //----------------------------------------------------------------------------- mglCanvasGL::~mglCanvasGL(){} //----------------------------------------------------------------------------- @@ -189,6 +189,12 @@ void mglCanvasGL::Clf(mglColor Back) gl_clf(Back); } //----------------------------------------------------------------------------- +void mglCanvasGL::Clf(const char *col) +{ + mglCanvas::Clf(col); + gl_clf(mglColor(BDef[0]/255.,BDef[1]/255.,BDef[2]/255.)); +} +//----------------------------------------------------------------------------- void mglCanvasGL::gl_clf(mglColor Back) { if(Back==NC) Back = WC; @@ -246,6 +252,7 @@ unsigned char **mglCanvasGL::GetRGBLines(long &width, long &height, unsigned cha p = (unsigned char **)malloc(height * sizeof(unsigned char *)); f = (unsigned char *) malloc(width*height * sizeof(unsigned char)*d); for(long i=0;iNeedStop()) return 0; + curGr = gr->Self(); std::wstring arg[1024]; str=mgl_trim_ws(str); long n,k=0,m=0,mm=0,res; @@ -612,9 +614,8 @@ int mglParser::Parse(mglGraph *gr, std::wstring str, long pos) if(n && k!=na+2) { char buf[64]; - snprintf(buf,64,"Bad arguments for %ls: %ld instead of %d\n", - a[0].w.c_str(),k-2,na); - gr->SetWarn(-1,buf); n = 1; + snprintf(buf,64,"Bad arguments for %ls: %ld instead of %d\n", a[0].w.c_str(),k-2,na); + buf[63]=0; gr->SetWarn(-1,buf); n = 1; } else if(n) { @@ -860,6 +861,7 @@ void mglParser::Execute(mglGraph *gr, int n, const wchar_t **text) else if(r==4) snprintf(buf,64,"\nUnbalanced ' in line %ld\n", i+1); else if(gr->GetWarn()>0) snprintf(buf,64," in line %ld\n", i+1); else *buf=0; + buf[63] = 0; if(*buf) gr->SetWarn(-2,buf); if(r>0 && r<5) res=r; } diff --git a/src/pixel.cpp b/src/pixel.cpp index c22949b..9e94096 100644 --- a/src/pixel.cpp +++ b/src/pixel.cpp @@ -621,6 +621,8 @@ void mglCanvas::Finish() static mglMatrix bp; if(Quality==MGL_DRAW_NONE) return; #if MGL_HAVE_PTHREAD + pthread_mutex_lock(&mutexPrm); + pthread_mutex_lock(&mutexPnt); pthread_mutex_lock(&mutexClf); #elif MGL_HAVE_OMP omp_set_lock(&lockClf); @@ -654,6 +656,8 @@ void mglCanvas::Finish() } #if MGL_HAVE_PTHREAD pthread_mutex_unlock(&mutexClf); + pthread_mutex_unlock(&mutexPnt); + pthread_mutex_unlock(&mutexPrm); #elif MGL_HAVE_OMP omp_unset_lock(&lockClf); #endif @@ -899,7 +903,7 @@ bool MGL_LOCAL_PURE visible(long i, long j, const unsigned char m[8], mreal pw, // register int ii = int(0.5+(i*c+j*s)/pw)%8, jj = int(0.5+(j*c-i*s)/pw)%8; // if(ii<0) ii+=8; if(jj<0) jj+=8; register int ii = int(0.5+(i*c+j*s)/pw)&7, jj = int(0.5+(j*c-i*s)/pw)&7; - return m[jj] & (1<dd) v += (u-dd)*(u-dd); if(v>pw*pw) continue; - if(!(pd & ( 1<dd) v += (u-dd)*(u-dd); if(v>pw*pw) continue; - if(!(pd & (1<dd) v += (u-dd)*(u-dd); register float pw=dr->PenWidth, dpw=3; if(dr->ObjId==HighId) { pw *= 2; dpw=2; } - if(v>pw*pw || !(dr->PDef & ( 1<pPos+u/pw/1.5, 16)) ) )) return; + if(v>pw*pw || !(dr->PDef & ( 1L<pPos+u/pw/1.5, 16)) ) )) return; mglPnt p = p1+d*(u/dd); unsigned char r[4]; col2int(p,r,dr->ObjId); diff --git a/src/plot.cpp b/src/plot.cpp index 592655b..0df5b3e 100644 --- a/src/plot.cpp +++ b/src/plot.cpp @@ -214,22 +214,27 @@ void MGL_EXPORT mgl_candle_xyv(HMGL gr, HCDT x, HCDT v1, HCDT v2, HCDT y1, HCDT if(y1->GetNx()!=n || y2->GetNx()!=n) { gr->SetWarn(mglWarnDim,"Candle"); return; } static int cgid=1; gr->StartGroup("Candle",cgid++); - gr->SaveState(opt); gr->SetPenPal(pen,&pal); - gr->NextColor(pal); gr->Reserve(8*n); + gr->SaveState(opt); gr->SetPenPal(pen,&pal); gr->Reserve(8*n); bool sh = mglchr(pen,'!'); + bool wire = mglchr(pen,'#'); mreal dv=nx>n?1:0; if(mglchr(pen,'<')) dv = 1; if(mglchr(pen,'^')) dv = 0; if(mglchr(pen,'>')) dv = -1; mreal zm = gr->AdjustZMin(); + mreal c1,c2; c2=c1=gr->NextColor(pal); + bool col2 = (gr->GetNumPal(pal)==2 && !sh); + if(col2) c2 = gr->NextColor(pal); for(long i=0;iv(i), m2 = v2->v(i), xx = x->v(i); - mreal d = iv(i+1)-xx : xx-x->v(i-1); + mreal d = iv(i+1)-xx : xx-x->v(i-1), c; mreal x1 = xx + d/2*(dv-gr->BarWidth); mreal x2 = x1 + gr->BarWidth*d; xx = (x1+x2)/2; - mreal c = sh ? gr->NextColor(pal,i):gr->CDef; + if(sh) c = gr->NextColor(pal,i); + else if(wire) c = (i>0 && m2>v2->v(i-1))?c2:c1; + else c = (m1>m2)?c1:c2; long n1 = gr->AddPnt(mglPoint(xx,y1->v(i),zm),c); long n2 = gr->AddPnt(mglPoint(xx,m1,zm),c); gr->line_plot(n1,n2); @@ -243,7 +248,7 @@ void MGL_EXPORT mgl_candle_xyv(HMGL gr, HCDT x, HCDT v1, HCDT v2, HCDT y1, HCDT n4 = gr->AddPnt(mglPoint(x2,m2,zm),c); gr->line_plot(n1,n2); gr->line_plot(n1,n3); gr->line_plot(n4,n2); gr->line_plot(n4,n3); - if(m1>m2) gr->quad_plot(n1,n2,n3,n4); + if(m1>m2 || (col2 && !wire)) gr->quad_plot(n1,n2,n3,n4); } if(d1) delete y1; if(d2) delete y2; gr->EndGroup(); @@ -1054,7 +1059,6 @@ void MGL_EXPORT mgl_barh_yx(HMGL gr, HCDT y, HCDT v, const char *pen, const char bool wire = mglchr(pen,'#'); bool above = mglchr(pen,'a'), fall = mglchr(pen,'f'); if(above) fall = false; - mreal c1,c2; mreal *dd=new mreal[n], x0,xp,dv=ny>n?1:0; if(mglchr(pen,'<')) dv = 1; if(mglchr(pen,'^')) dv = 0; @@ -1067,7 +1071,7 @@ void MGL_EXPORT mgl_barh_yx(HMGL gr, HCDT y, HCDT v, const char *pen, const char for(long j=0;jNeedStop()) break; - c2=c1=gr->NextColor(pal); + mreal c1,c2; c2=c1=gr->NextColor(pal); if(gr->GetNumPal(pal)==2*m && !sh) c2 = gr->NextColor(pal); long mx = jGetNy() ? j:0, my = jGetNy() ? j:0; xp = x0 = gr->GetOrgX('y'); @@ -1127,7 +1131,7 @@ void MGL_EXPORT mgl_ohlc_x(HMGL gr, HCDT x, HCDT open, HCDT high, HCDT low, HCDT { gr->SetWarn(mglWarnDim,"OHLC"); return; } gr->SaveState(opt); static int cgid=1; gr->StartGroup("OHLC",cgid++); - mreal dv=nx>n?1:0,dd,vv,x1,x2,cc; + mreal dv=nx>n?1:0; if(mglchr(pen,'<')) dv = 1; if(mglchr(pen,'^')) dv = 0; if(mglchr(pen,'>')) dv = -1; @@ -1139,24 +1143,27 @@ void MGL_EXPORT mgl_ohlc_x(HMGL gr, HCDT x, HCDT open, HCDT high, HCDT low, HCDT for(long j=0;jNeedStop()) break; - cc=gr->NextColor(pal); + mreal c1,c2; c2=c1=gr->NextColor(pal); + if(gr->GetNumPal(pal)==2*m && !sh) c2 = gr->NextColor(pal); mx = jGetNy() ? j:0; for(long i=0;iv(i,mx); dd = iv(i+1)-vv : vv-x->v(i-1); x1 = vv + dd/2*(dv-gr->BarWidth); x2 = x1 + gr->BarWidth*dd; x2 = (x2-x1)/m; x1 += j*x2; x2 += x1; vv = (x2+x1)/2; - mreal c = sh ? gr->NextColor(pal,i):cc; + if(sh) c1=c2=gr->NextColor(pal,i); register long n1,n2; - dd = open->v(i,j); - n1=gr->AddPnt(mglPoint(x1,dd,zVal),c); - n2=gr->AddPnt(mglPoint(vv,dd,zVal),c); - gr->line_plot(n1,n2); dd = close->v(i,j); + mreal c = (i==0 || dd>=close->v(i-1,j)) ? c1:c2; n1=gr->AddPnt(mglPoint(vv,dd,zVal),c); n2=gr->AddPnt(mglPoint(x2,dd,zVal),c); gr->line_plot(n1,n2); + dd = open->v(i,j); + n1=gr->AddPnt(mglPoint(x1,dd,zVal),c); + n2=gr->AddPnt(mglPoint(vv,dd,zVal),c); + gr->line_plot(n1,n2); n1=gr->AddPnt(mglPoint(vv,low->v(i,j),zVal),c); n2=gr->AddPnt(mglPoint(vv,high->v(i,j),zVal),c); gr->line_plot(n1,n2); diff --git a/src/surf.cpp b/src/surf.cpp index 0890e99..3734b42 100644 --- a/src/surf.cpp +++ b/src/surf.cpp @@ -74,8 +74,8 @@ void MGL_EXPORT mgl_fsurf(HMGL gr, const char *eqZ, const char *sch, const char mreal r = gr->SaveState(opt); long n = (mgl_isnan(r) || r<=0) ? 100:long(r+0.5); mglData z(n,n),res; - mglDataV x(n,n); x.Fill(gr->Min.x,gr->Max.x,'x'); x.s=L"x"; - mglDataV y(n,n); y.Fill(gr->Min.y,gr->Max.y,'y'); y.s=L"y"; + mglDataV x(n,n,1, gr->Min.x,gr->Max.x,'x'); x.s=L"x"; + mglDataV y(n,n,1, gr->Min.y,gr->Max.y,'y'); y.s=L"y"; mglDataV t(n,n); t.s=L"#$mgl"; std::vector list; list.push_back(&x); list.push_back(&y); list.push_back(&t); @@ -90,8 +90,8 @@ void MGL_EXPORT mgl_fsurf_xyz(HMGL gr, const char *eqX, const char *eqY, const c mreal r = gr->SaveState(opt); long n = (mgl_isnan(r) || r<=0) ? 100:long(r+0.5); mglData z(n,n), x(n,n), y(n,n), res; - mglDataV u(n,n); u.Fill(0,1,'x'); u.s=L"u"; - mglDataV v(n,n); v.Fill(0,1,'y'); v.s=L"v"; + mglDataV u(n,n,1, 0,1,'x'); u.s=L"u"; + mglDataV v(n,n,1, 0,1,'y'); v.s=L"v"; mglDataV t(n,n); t.s=L"#$mgl"; std::vector list; list.push_back(&u); list.push_back(&v); list.push_back(&t); diff --git a/texinfo/core_en.texi b/texinfo/core_en.texi index a7b8026..b31e7da 100644 --- a/texinfo/core_en.texi +++ b/texinfo/core_en.texi @@ -2311,7 +2311,7 @@ These functions draw boxplot (also known as a box-and-whisker diagram) at points @deftypefnx {C function} @code{void} mgl_candle_yv (@code{HMGL} gr, @code{HCDT} v1, @code{HCDT} v2, @code{HCDT} y1, @code{HCDT} y2, @code{const char *}pen, @code{const char *}opt) @deftypefnx {C function} @code{void} mgl_candle_xyv (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} v1, @code{HCDT} v2, @code{HCDT} y1, @code{HCDT} y2, @code{const char *}pen, @code{const char *}opt) @end ifclear -These functions draw candlestick chart at points @var{x}[i]. This is a combination of a line-chart and a bar-chart, in that each bar represents the range of price movement over a given time interval. Wire (or white) candle correspond to price growth @var{v1}[i]<@var{v2}[i], opposite case -- solid (or dark) candle. "Shadows" show the minimal @var{y1} and maximal @var{y2} prices. If @var{v2} is absent then it is determined as @var{v2}[i]=@var{v1}[i+1]. See also @ref{plot}, @ref{bars}, @ref{ohlc}, @ref{barwidth}. @sref{Candle sample} +These functions draw candlestick chart at points @var{x}[i]. This is a combination of a line-chart and a bar-chart, in that each bar represents the range of price movement over a given time interval. Wire (or white) candle correspond to price growth @var{v1}[i]<@var{v2}[i], opposite case -- solid (or dark) candle. You can give different colors for growth and decrease values if number of specified colors is equal to 2. If @var{pen} contain @samp{#} then the wire candle will be used even for 2-color scheme. "Shadows" show the minimal @var{y1} and maximal @var{y2} prices. If @var{v2} is absent then it is determined as @var{v2}[i]=@var{v1}[i+1]. See also @ref{plot}, @ref{bars}, @ref{ohlc}, @ref{barwidth}. @sref{Candle sample} @end deftypefn @anchor{ohlc} @@ -2323,7 +2323,7 @@ These functions draw candlestick chart at points @var{x}[i]. This is a combinati @deftypefnx {C function} @code{void} mgl_ohlc (@code{HMGL} gr, @code{HCDT} o, @code{HCDT} h, @code{HCDT} l, @code{HCDT} c, @code{const char *}pen, @code{const char *}opt) @deftypefnx {C function} @code{void} mgl_ohlc_x (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} o, @code{HCDT} h, @code{HCDT} l, @code{HCDT} c, @code{const char *}pen, @code{const char *}opt) @end ifclear -These functions draw Open-High-Low-Close diagram. This diagram show vertical line for between maximal(high @var{h}) and minimal(low @var{l}) values, as well as horizontal lines before/after vertical line for initial(open @var{o})/final(close @var{c}) values of some process (usually price). See also @ref{candle}, @ref{plot}, @ref{barwidth}. @sref{OHLC sample} +These functions draw Open-High-Low-Close diagram. This diagram show vertical line for between maximal(high @var{h}) and minimal(low @var{l}) values, as well as horizontal lines before/after vertical line for initial(open @var{o})/final(close @var{c}) values of some process (usually price). You can give different colors for up and down values (when closing values higher or not as in previous point) if number of specified colors is equal to 2*number of curves. See also @ref{candle}, @ref{plot}, @ref{barwidth}. @sref{OHLC sample} @end deftypefn @@ -3380,10 +3380,10 @@ Fit data along x-, y- and z-directions for array specified parametrically @var{a @end deftypefn @anchor{fit} -@deftypefn {MGL command} {} fit res adat sdat 'func' 'var' [ini=0] -@deftypefnx {MGL command} {} fit res xdat adat sdat 'func' 'var' [ini=0] -@deftypefnx {MGL command} {} fit res xdat ydat adat sdat 'func' 'var' [ini=0] -@deftypefnx {MGL command} {} fit res xdat ydat zdat adat sdat 'func' 'var' [ini=0] +@deftypefn {MGL command} {} fit res adat 'func' 'var' [ini=0] +@deftypefnx {MGL command} {} fit res xdat adat 'func' 'var' [ini=0] +@deftypefnx {MGL command} {} fit res xdat ydat adat 'func' 'var' [ini=0] +@deftypefnx {MGL command} {} fit res xdat ydat zdat adat 'func' 'var' [ini=0] @ifclear UDAV @deftypefnx {Method on @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""}) @deftypefnx {Method on @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""}) diff --git a/texinfo/core_ru.texi b/texinfo/core_ru.texi index bb7c2d5..b2c87f5 100644 --- a/texinfo/core_ru.texi +++ b/texinfo/core_ru.texi @@ -2218,7 +2218,7 @@ Draw bitmap (logo) along whole axis range, which can be changed by @ref{Command @deftypefnx {Функция С} @code{void} mgl_candle_yv (@code{HMGL} gr, @code{HCDT} v1, @code{HCDT} v2, @code{HCDT} y1, @code{HCDT} y2, @code{const char *}pen, @code{const char *}opt) @deftypefnx {Функция С} @code{void} mgl_candle_xyv (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} v1, @code{HCDT} v2, @code{HCDT} y1, @code{HCDT} y2, @code{const char *}pen, @code{const char *}opt) @end ifclear -Функции рисуют candlestick chart в точках @var{x}[i]. Этот график показывает прямоугольником ("свечой") диапазон изменения величины. Прозрачная (белая) свеча соответствует росту величины @var{v1}[i]<@var{v2}[i], чёрная -- уменьшению. "Тени" показывают минимальное @var{y1} и максимальное @var{y2} значения. Если @var{v2} отсутствует, то он определяется как @var{v2}[i]=@var{v1}[i+1]. См. также @ref{plot}, @ref{bars}, @ref{ohlc}, @ref{barwidth}. @sref{Candle sample} +Функции рисуют candlestick chart в точках @var{x}[i]. Этот график показывает прямоугольником ("свечой") диапазон изменения величины. Прозрачная (белая) свеча соответствует росту величины @var{v1}[i]<@var{v2}[i], чёрная -- уменьшению. "Тени" показывают минимальное @var{y1} и максимальное @var{y2} значения. Если @var{v2} отсутствует, то он определяется как @var{v2}[i]=@var{v1}[i+1]. Можно использовать разные цвета для растущих и падающих дней если число указанных цветов равно удвоенному числу кривых для построения. Если @var{pen} содержит @samp{#}, то прозрачная свеча будет использована и при 2-цветной схеме. См. также @ref{plot}, @ref{bars}, @ref{ohlc}, @ref{barwidth}. @sref{Candle sample} @end deftypefn @anchor{ohlc} @@ -2230,7 +2230,7 @@ Draw bitmap (logo) along whole axis range, which can be changed by @ref{Command @deftypefnx {Функция С} @code{void} mgl_ohlc (@code{HMGL} gr, @code{HCDT} o, @code{HCDT} h, @code{HCDT} l, @code{HCDT} c, @code{const char *}pen, @code{const char *}opt) @deftypefnx {Функция С} @code{void} mgl_ohlc_x (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} o, @code{HCDT} h, @code{HCDT} l, @code{HCDT} c, @code{const char *}pen, @code{const char *}opt) @end ifclear -Функции рисуют Open-High-Low-Close диаграмму. Этот график содержит вертикальные линии между максимальным @var{h} и минимальным @var{l} значениями, и горизонтальные линии перед/после вертикальной линии для начального @var{o} и конечного @var{c} значений процесса (обычно цены). См. также @ref{candle}, @ref{plot}, @ref{barwidth}. @sref{OHLC sample} +Функции рисуют Open-High-Low-Close диаграмму. Этот график содержит вертикальные линии между максимальным @var{h} и минимальным @var{l} значениями, и горизонтальные линии перед/после вертикальной линии для начального @var{o} и конечного @var{c} значений процесса (обычно цены). Можно использовать разные цвета для растущих и падающих дней если число указанных цветов равно удвоенному числу кривых для построения. См. также @ref{candle}, @ref{plot}, @ref{barwidth}. @sref{OHLC sample} @end deftypefn @@ -3292,10 +3292,10 @@ Draw bitmap (logo) along whole axis range, which can be changed by @ref{Command @end deftypefn @anchor{fit} -@deftypefn {Команда MGL} {} fit res adat sdat 'func' 'var' [ini=0] -@deftypefnx {Команда MGL} {} fit res xdat adat sdat 'func' 'var' [ini=0] -@deftypefnx {Команда MGL} {} fit res xdat ydat adat sdat 'func' 'var' [ini=0] -@deftypefnx {Команда MGL} {} fit res xdat ydat zdat adat sdat 'func' 'var' [ini=0] +@deftypefn {Команда MGL} {} fit res adat 'func' 'var' [ini=0] +@deftypefnx {Команда MGL} {} fit res xdat adat 'func' 'var' [ini=0] +@deftypefnx {Команда MGL} {} fit res xdat ydat adat 'func' 'var' [ini=0] +@deftypefnx {Команда MGL} {} fit res xdat ydat zdat adat 'func' 'var' [ini=0] @ifclear UDAV @deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""}) @deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""}) diff --git a/texinfo/doc_en.texi b/texinfo/doc_en.texi index 1e46da6..5d09f28 100644 --- a/texinfo/doc_en.texi +++ b/texinfo/doc_en.texi @@ -72,45 +72,45 @@ This file documents the Mathematical Graphic Library (MathGL), a collection of c MathGL -@comment
-@comment -@comment +
+ + @end html @end macro @macro external {} @html -@comment
-@comment -@comment -@comment
+
+ + +
@comment -@comment -@comment
+ +