cmake_minimum_required(VERSION 2.8.9)
+if(POLICY CMP0043)
+ cmake_policy(SET CMP0043 OLD)
+endif()
project( MathGL )
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")
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")
-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
void save(mglGraph *gr,const char *name,const char *suf);\r
void test(mglGraph *gr)\r
{\r
-// gr->Rotate(40,60); gr->Fog(1); gr->Box(); return;\r
mglParse par;\r
par.Execute(gr,"load '/home/balakin/mathgl-code/mathgl-2x/build/examples/libmgl_module.so':baxis\n");\r
// par.Execute(gr,"subplot 1 1 0:#rotate 40 60\nperspective 1.22:box:axis\n");\r
gr->WriteOBJ("fexport.obj");\r
gr->WritePRC("fexport.prc");\r
gr->WriteJSON("fexport.json");\r
- \r
+\r
gr->ExportMGLD("fexport.mgld");\r
gr->Clf();\r
gr->ImportMGLD("fexport.mgld");\r
{\r
mgl_set_test_mode(true); test(gr);\r
time(&en); printf("time is %g sec\n",difftime(en,st));\r
+#if MGL_HAVE_PNG\r
gr->WritePNG("test.png","",false);\r
+#else\r
+ gr->WriteBMP("test.bmp");\r
+#endif\r
gr->WriteSVG("test.svg");\r
gr->WriteEPS("test.eps");\r
printf("Messages:%s\n",gr->Message());\r
#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
/// 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);
template <class T> class mglStack\r
{\r
T** dat;\r
- size_t pb; ///< size of buffer (real size is 2^pb == 1<<pb)\r
+ size_t pb; ///< size of buffer (real size is 2^pb == 1L<<pb)\r
size_t np; ///< allocated pointers\r
size_t m; ///< used pointers (allocated size is m*nb)\r
size_t n; ///< used cells\r
{\r
np=st.np; dat = (T**)malloc(np*sizeof(T*));\r
pb=st.pb; m=n=0; reserve(st.n);\r
- for(size_t i=0;i<m;i++) memcpy(dat[i],st.dat[i],(1<<pb)*sizeof(T));\r
+ for(size_t i=0;i<m;i++) memcpy(dat[i],st.dat[i],(1L<<pb)*sizeof(T));\r
n=st.n; mutex = 0;\r
}\r
mglStack(size_t Pbuf=10)\r
{ np=16; pb=Pbuf; dat = (T**)malloc(np*sizeof(T*));\r
- dat[0] = new T[1<<pb]; n=0; m=1; mutex = 0; }\r
+ dat[0] = new T[1L<<pb]; n=0; m=1; mutex = 0; }\r
~mglStack() { clear(); delete [](dat[0]); free(dat); }\r
inline void set_mutex(void *m) { mutex = m; }\r
void reserve(size_t num)\r
num = 1+ (num>>pb);\r
if(num>np)\r
{ dat = (T**)realloc(dat, num*sizeof(T*)); np=num; }\r
- for(size_t i=m;i<num;i++) dat[i] = new T[1<<pb];\r
+ for(size_t i=m;i<num;i++) dat[i] = new T[1L<<pb];\r
m = num;\r
}\r
}\r
#endif\r
}\r
for(size_t i=0;i<m;i++) delete [](dat[i]);\r
- dat[0] = new T[1<<pb]; n=0; m=1;\r
+ dat[0] = new T[1L<<pb]; n=0; m=1;\r
if(mutex)\r
{\r
#if MGL_HAVE_PTHREAD\r
const mglStack<T> &operator=(const mglStack<T> &st)\r
{\r
pb=st.pb; clear(); reserve(st.n);\r
- for(size_t i=0;i<st.m && i<m;i++) memcpy(dat[i],st.dat[i],(1<<pb)*sizeof(T));\r
+ for(size_t i=0;i<st.m && i<m;i++) memcpy(dat[i],st.dat[i],(1L<<pb)*sizeof(T));\r
n = st.n; return st;\r
}\r
};\r
#include <wchar.h>\r
\r
#if defined(_MSC_VER)\r
-#if (_MSC_VER<1800)\r
+#if (_MSC_VER<=1800)\r
#define collapse(a) // MSVS don't support OpenMP 3.*\r
#define strtoull _strtoui64\r
#define hypot _hypot\r
#define mgl_sign(a) ((a)<0 ? -1:1)\r
#endif\r
//-----------------------------------------------------------------------------\r
-#define SMOOTH_NONE 0\r
-#define SMOOTH_LINE_3 1\r
-#define SMOOTH_LINE_5 2\r
-#define SMOOTH_QUAD_5 3\r
-//-----------------------------------------------------------------------------\r
-#define MGL_HIST_IN 0\r
-#define MGL_HIST_SUM 1\r
-#define MGL_HIST_UP 2\r
-#define MGL_HIST_DOWN 3\r
-//-----------------------------------------------------------------------------\r
enum{ // types of predefined curvelinear coordinate systems\r
mglCartesian = 0, // no transformation\r
mglPolar,\r
#include <complex.h>\r
#if MGL_USE_DOUBLE\r
typedef double _Complex mdual;\r
+#ifndef _Complex_I\r
+#define _Complex_I (double _Complex){0, 1}\r
+#endif\r
#else\r
typedef float _Complex mdual;\r
+#ifndef _Complex_I\r
+#define _Complex_I (float _Complex){0, 1}\r
+#endif\r
#endif\r
#define mgl_abs(x) cabs(x)\r
#endif\r
#define MGL_COLOR_MASK 0xffffff00\r
#define MGL_FONT_STYLE 0x3f000000\r
//-----------------------------------------------------------------------------\r
-#ifdef WIN32 // a man ask to use built-in font under Windows\r
-#define MGL_DEF_FONT_NAME 0\r
-#else\r
-#define MGL_DEF_FONT_NAME "STIX"\r
-#endif\r
-//-----------------------------------------------------------------------------\r
struct mglGlyphDescr\r
{\r
wchar_t id; ///< Unicode ID for glyph\r
\r
void SetQuality(int =0) { Quality=2; }\r
void Finish();\r
- void SetSize(int ,int ) {}\r
+ void SetSize(int ,int ,bool clf=true) { if(clf) Clf(); }\r
void View(mreal tetX,mreal tetY,mreal tetZ);\r
void Zoom(mreal x1, mreal y1, mreal x2, mreal y2);\r
/* int NewFrame();\r
void Light(int n, bool enable);\r
void AddLight(int n,mglPoint r,mglPoint d, char c='w', mreal bright=0.5, mreal ap=0);\r
void Clf(mglColor Back=NC);\r
+ void Clf(const char *col);\r
\r
protected:\r
// provide fastest variant for usual points (not glyphs or marks)\r
bool Stop; ///< Stop command was. Flag prevent further execution\r
mglCommand *Cmd; ///< Table of MGL commands (can be changed by user). It MUST be sorted by 'name'!!!\r
long InUse; ///< Smart pointer (number of users)\r
+ const mglBase *curGr; ///< Current grapher\r
\r
mglParser(bool setsize=false);\r
virtual ~mglParser();\r
mglDraw *draw; ///< Class for drawing -- need to call directly due to inheritance mechanism\r
QString mousePos; ///< Last mouse position\r
QPixmap pic; ///< Pixmap for drawing (changed by update)\r
+ QImage img; ///< Last used HQ image\r
double tet, phi; ///< Rotation angles\r
double per; ///< Value of perspective ( must be in [0,1) )\r
bool alpha; ///< Transparency state\r
};\r
//-----------------------------------------------------------------------------\r
/// Convert bitmap from mglCanvasWnd to QPixmap\r
-void mglConvertFromGraph(QPixmap &pic, mglCanvas *gr, uchar **buf);\r
+void mglConvertFromGraph(QPixmap &pic, mglCanvas *gr, uchar **buf, QImage *out=NULL);\r
/// Make menu, toolbars and return popup menu for MainWindow\r
MGL_EXPORT QMenu *mglMakeMenu(QMainWindow* Wnd, QMathGL* QMGL, QSpinBox*& tet, QSpinBox*& phi);\r
//-----------------------------------------------------------------------------\r
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.
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.
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);
}
}
// 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();
}
// 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);
}
mathgl.Graph.prototype.destroy = function() {
+ // clear active timeouts
+ for (var i = 0, l = this.__activeTimeoutHandlers.length; i<l; i++) {
+ var th = this.__activeTimeoutHandlers.pop();
+ clearTimeout(th);
+ }
this.__view.destroy();
this.__view = null;
this.__backend = null;
message(SEND_ERROR "Couldn't find numpy.")
endif(NOT NUMPY_INCLUDE_PATH)
- include_directories(${PYTHON_INCLUDE_DIR})
+ include_directories(${PYTHON_INCLUDE_DIR} ${NUMPY_INCLUDE_PATH})
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(prefix='${CMAKE_INSTALL_PREFIX}')"
OUTPUT_VARIABLE MGL_PYTHON_SITE_PACKAGES
execute_process(COMMAND ${oct_prog} -p API_VERSION
OUTPUT_VARIABLE oct_api
OUTPUT_STRIP_TRAILING_WHITESPACE)
- execute_process(COMMAND ${oct_prog} -p OCTINCLUDEDIR
+ execute_process(COMMAND ${oct_mk} -p INCFLAGS
OUTPUT_VARIABLE oct_inc
OUTPUT_STRIP_TRAILING_WHITESPACE)
+ separate_arguments(oct_inc)
message(STATUS "${oct_prog} ${oct_host} ${oct_api}")
set(oct_arch ${oct_host}-${oct_api})
set(pkg_name mathgl)
set(mgl_pkg_dir ${MathGL_BINARY_DIR}/lang/${pkg_name}/inst/${oct_arch})
- include_directories(${oct_inc} ${oct_inc}/..)
+ add_compile_options(${oct_inc})
SET(SWIG_MODULE_mgl-oct_EXTRA_DEPS numpy.i ${src_imp_dep})
SWIG_ADD_MODULE(mgl-oct octave mathgl.i)
SWIG_LINK_LIBRARIES(mgl-oct mgl)
set_target_properties(mgl-oct PROPERTIES OUTPUT_NAME mathgl PREFIX "" SUFFIX ".oct" BUILD_WITH_INSTALL_RPATH ON)
- get_target_property(mgl-oct_filename mgl-oct LOCATION)
add_custom_command(OUTPUT mathgl.tar.gz
COMMAND ${CMAKE_COMMAND} -E make_directory ${mgl_pkg_dir}
COMMAND ${CMAKE_COMMAND} -E copy ${MathGL_SOURCE_DIR}/COPYING ${MathGL_BINARY_DIR}/lang/${pkg_name}
COMMAND ${CMAKE_COMMAND} -E copy ${MathGL_SOURCE_DIR}/lang/DESCRIPTION ${MathGL_BINARY_DIR}/lang/${pkg_name}
COMMAND ${CMAKE_COMMAND} -E copy ${MathGL_SOURCE_DIR}/lang/INDEX ${MathGL_BINARY_DIR}/lang/${pkg_name}
COMMAND ${CMAKE_COMMAND} -E copy ${MathGL_SOURCE_DIR}/lang/PKG_ADD_template ${MathGL_BINARY_DIR}/lang/${pkg_name}
- COMMAND ${CMAKE_COMMAND} -E copy ${mgl-oct_filename} ${mgl_pkg_dir}
+ COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:mgl-oct> ${mgl_pkg_dir}
COMMAND ${oct_tar} cpzf mathgl.tar.gz ${pkg_name}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/lang
DEPENDS mgl-oct
% \fi
%
% \iffalse
-%<package>\def\mgl@name{mgltex}
-%<package>\def\mgl@date{2014/09/16}
-%<package>\def\mgl@version{1.0}
-%<package>\def\mgl@description{Embed MGL code into LaTeX documents}
-%<package>
+%
%<package>\NeedsTeXFormat{LaTeX2e}
-%<package>\ProvidesPackage{\mgl@name}[\mgl@date\space v.\mgl@version\space\mgl@description]
+%<package>\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
%</driver>
% \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
% 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}}
% \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}
% \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}
% \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]
% \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}
% \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.
%
% }
% \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{<environment>}
+% <contents of the environment>
+% \end{<environment>}
+% \end{verbatim}
+% The following forms of use could cause problems:
+% \begin{verbatim}
+% \begin{<environment>}<contents of the environment>\end{<environment>}
+% \end{verbatim}
+% \begin{verbatim}
+% \begin{<environment>}<contents of the environment>
+% \end{<environment>}
+% \end{verbatim}
+% \begin{verbatim}
+% \begin{<environment>}
+% <contents of the environment>
+% \end{<environment>}<text>
+% \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}%
\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}}
\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,}}
\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,}}
\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\}}%
\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%
}{%
\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{%
\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\}}%
\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}%
\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\}}%
\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
--- /dev/null
+%%
+%% Copyright (C) 2014 by Diego Sejas <diego.mathematician@gmail.com>
+%%
+%% 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 <http://www.gnu.org/licenses/>.
+%%
+
+\input docstrip.tex
+\keepsilent
+
+\usedir{tex/latex/mgltex}
+
+\preamble
+
+This is a generated file.
+
+Copyright (C) 2014 by Diego Sejas <diego.mathematician@gmail.com>
+
+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 <http://www.gnu.org/licenses/>.
+
+\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
+++ /dev/null
-%%
-%% Copyright (C) 2014 by Diego Sejas <diego.mathematician@gmail.com>
-%%
-%% 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 <http://www.gnu.org/licenses/>.
-%%
-
-\input docstrip.tex
-\keepsilent
-
-\usedir{tex/latex/mgltex}
-
-\preamble
-
-This is a generated file.
-
-Copyright (C) 2014 by Diego Sejas <diego.mathematician@gmail.com>
-
-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 <http://www.gnu.org/licenses/>.
-
-\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
%% You should have received a copy of the GNU General Public License along
%% with this program. If not, see <http://www.gnu.org/licenses/>.
%%
-\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}}
\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,}}
\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,}}
\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%
}
\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%
\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}%
}
\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}%
}
\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}%
}
\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%
\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}%
\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%
}
\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}%
}
\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'.
-\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}
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}
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'}
\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}
\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
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)
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);
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");
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();
}
char *mgl_strdup(const char *s)\r
{\r
char *r = (char *)malloc((strlen(s)+1)*sizeof(char));\r
- memcpy(r,s,(strlen(s)+1)*sizeof(char));\r
+ if(r) memcpy(r,s,(strlen(s)+1)*sizeof(char));\r
return r;\r
}\r
//-----------------------------------------------------------------------------\r
{\r
LightScale(&B);\r
char buf[128];\r
- snprintf(buf,128,"%s_%d",name,id);\r
+ snprintf(buf,128,"%s_%d",name,id); buf[127]=0;\r
StartAutoGroup(buf);\r
}\r
//-----------------------------------------------------------------------------\r
//-----------------------------------------------------------------------------\r
mreal mglBase::NextColor(long &id)\r
{\r
- long i=abs(id)/256, n=Txt[i].n, p=abs(id)&0xff;\r
+ long i=labs(id)/256, n=Txt[i].n, p=labs(id)&0xff;\r
if(id>=0) { p=(p+1)%n; id = 256*i+p; }\r
CDef = i + (n>0 ? (p+0.5)/n : 0); CurrPal++;\r
sprintf(last_style+11,"{&%g}",CDef);\r
//-----------------------------------------------------------------------------\r
mreal mglBase::NextColor(long id, long sh)\r
{\r
- long i=abs(id)/256, n=Txt[i].n, p=abs(id)&0xff;\r
+ long i=labs(id)/256, n=Txt[i].n, p=labs(id)&0xff;\r
if(id>=0) p=(p+sh)%n;\r
mreal cc = i + (n>0 ? (p+0.5)/n : 0);\r
sprintf(last_style+11,"{&%g}",cc);\r
char buf[256];\r
va_list lst;\r
va_start(lst,str);\r
- vsnprintf(buf,256,str,lst);\r
+ vsnprintf(buf,256,str,lst); buf[255]=0;\r
va_end(lst);\r
printf("TEST: %s\n",buf);\r
fflush(stdout);\r
Pnt.clear(); Prm.clear(); Ptx.clear(); Glf.clear(); ClearPrmInd();\r
Txt.clear(); Txt.reserve(3);\r
mglTexture t1(MGL_DEF_PAL,-1), t2(MGL_DEF_SCH,1);\r
- MGL_PUSH(Txt,t1,mutexTxt);\r
- MGL_PUSH(Txt,t2,mutexTxt);\r
+ Txt.push_back(t1); Txt.push_back(t2); // No extra lock is required\r
}\r
#if MGL_HAVE_PTHREAD\r
pthread_mutex_unlock(&mutexAct);\r
int fdig = int(log10(v)); fdig = fdig>0?(fdig<dig?dig-fdig:0):dig;\r
ff[2] = fdig+'0'; ee[2] = dig+'0';\r
snprintf(se,64,ee,v); snprintf(sf,64,ff,v);\r
+ se[63] = sf[63] = 0;\r
long le=strlen(se), lf=strlen(sf), i;\r
\r
// clear fix format\r
if(mglchr(fmt,'-') && !(plus||tex)) // replace '-' by "\minus"\r
for(i=0;i<lf;i++) res += sf[i];\r
else\r
- for(i=0;i<lf;i++) res += sf[i]!='-'?sf[i]:L'−';\r
+ for(i=0;i<lf;i++) res += sf[i]!='-'?wchar_t(sf[i]):L'−';\r
if(tex) // TeX notation: 'e' -> "\cdot 10^{...}"\r
{\r
if(res[0]=='1' && (res[1]=='e' || res[1]=='E'))\r
long nx=t->p[0], kind=t->p[2];\r
dual *b=t->a;\r
const dual *a=t->b;\r
- if(kind==SMOOTH_LINE_3)\r
+ if(kind>0)\r
#if !MGL_HAVE_PTHREAD\r
#pragma omp parallel for\r
#endif\r
for(long i=t->id;i<t->n;i+=mglNumThr)\r
{\r
register long j = i%nx;\r
- if(j>0 && j<nx-1) b[i] = (a[i-1] + a[i] + a[i+1])/mreal(3);\r
- else b[i] = a[i];\r
- }\r
- else if(kind==SMOOTH_LINE_5)\r
-#if !MGL_HAVE_PTHREAD\r
-#pragma omp parallel for\r
-#endif\r
- for(long i=t->id;i<t->n;i+=mglNumThr)\r
- {\r
- register long j = i%nx;\r
- if(j>1 && j<nx-2) b[i] = (a[i-2] + a[i-1] + a[i] + a[i+1] + a[i+2])/mreal(5);\r
- else if(j==1 || j==nx-2) b[i] = (a[i-1] + a[i] + a[i+1])/mreal(3);\r
- else b[i] = a[i];\r
+ if(j-kind<0) j = i+kind-j;\r
+ else if(j+kind>nx-1) j = i+nx-1-j-kind;\r
+ else j=i;\r
+ for(long k=-kind;k<=kind;k++) b[i] += a[j+k]/mreal(2*kind+1);\r
}\r
- else if(kind==SMOOTH_QUAD_5)\r
+ else\r
#if !MGL_HAVE_PTHREAD\r
#pragma omp parallel for\r
#endif\r
long nx=t->p[0],ny=t->p[1], kind=t->p[2];\r
dual *b=t->a;\r
const dual *a=t->b;\r
- if(kind==SMOOTH_LINE_3)\r
-#if !MGL_HAVE_PTHREAD\r
-#pragma omp parallel for\r
-#endif\r
- for(long i=t->id;i<t->n;i+=mglNumThr)\r
- {\r
- register long j = (i/nx)%ny;\r
- if(j>0 && j<ny-1) b[i] = (a[i-nx] + a[i] + a[i+nx])/mreal(3);\r
- else b[i] = a[i];\r
- }\r
- else if(kind==SMOOTH_LINE_5)\r
+ if(kind>0)\r
#if !MGL_HAVE_PTHREAD\r
#pragma omp parallel for\r
#endif\r
for(long i=t->id;i<t->n;i+=mglNumThr)\r
{\r
register long j = (i/nx)%ny;\r
- if(j>1 && j<ny-2) b[i] = (a[i-2*nx] + a[i-nx] + a[i] + a[i+nx] + a[i+2*nx])/mreal(5);\r
- else if(j==1 || j==ny-2) b[i] = (a[i-nx] + a[i] + a[i+nx])/mreal(3);\r
- else b[i] = a[i];\r
+ if(j-kind<0) j = i+(kind-j)*nx;\r
+ else if(j+kind>ny-1) j = i+(ny-1-j-kind)*nx;\r
+ else j=i;\r
+ for(long k=-kind;k<=kind;k++) b[i] += a[j+k*nx]/mreal(2*kind+1);\r
}\r
- else if(kind==SMOOTH_QUAD_5)\r
+ else\r
#if !MGL_HAVE_PTHREAD\r
#pragma omp parallel for\r
#endif\r
register long nn=t->p[0]*t->p[1], nz=t->n/nn, kind=t->p[2];\r
dual *b=t->a;\r
const dual *a=t->b;\r
- if(kind==SMOOTH_LINE_3)\r
+ if(kind>0)\r
#if !MGL_HAVE_PTHREAD\r
#pragma omp parallel for\r
#endif\r
for(long i=t->id;i<t->n;i+=mglNumThr)\r
{\r
register long j = i/nn;\r
- if(j>0 && j<nz-1) b[i] = (a[i-nn] + a[i] + a[i+nn])/mreal(3);\r
- else b[i] = a[i];\r
+ if(j-kind<0) j = i+(kind-j)*nn;\r
+ else if(j+kind>nz-1) j = i+(nz-1-j-kind)*nn;\r
+ else j=i;\r
+ for(long k=-kind;k<=kind;k++) b[i] += a[j+k*nn]/mreal(2*kind+1);\r
}\r
- else if(kind==SMOOTH_LINE_5)\r
-#if !MGL_HAVE_PTHREAD\r
-#pragma omp parallel for\r
-#endif\r
- for(long i=t->id;i<t->n;i+=mglNumThr)\r
- {\r
- register long j = i/nn;\r
- if(j>1 && j<nz-2) b[i] = (a[i-2*nn] + a[i-nn] + a[i] + a[i+nn] + a[i+2*nn])/mreal(5);\r
- else if(j==1 || j==nz-2) b[i] = (a[i-nn] + a[i] + a[i+nn])/mreal(3);\r
- else b[i] = a[i];\r
- }\r
- else if(kind==SMOOTH_QUAD_5)\r
+ else\r
#if !MGL_HAVE_PTHREAD\r
#pragma omp parallel for\r
#endif\r
}\r
void MGL_EXPORT mgl_datac_smooth(HADT d, const char *dirs, mreal )\r
{\r
- long Type = SMOOTH_QUAD_5;\r
+ long Type = -1;\r
if(!dirs || *dirs==0) dirs = "xyz";\r
- if(strchr(dirs,'0') || strchr(dirs,'1')) return;\r
- if(strchr(dirs,'3')) Type = SMOOTH_LINE_3;\r
- if(strchr(dirs,'5')) Type = SMOOTH_LINE_5;\r
+ if(strchr(dirs,'0')) return;\r
+ if(strchr(dirs,'d'))\r
+ {\r
+ if(strchr(dirs,'1')) Type = 1;\r
+ if(strchr(dirs,'2')) Type = 2;\r
+ if(strchr(dirs,'3')) Type = 3;\r
+ if(strchr(dirs,'4')) Type = 4;\r
+ if(strchr(dirs,'5')) Type = 5;\r
+ if(strchr(dirs,'6')) Type = 6;\r
+ if(strchr(dirs,'7')) Type = 7;\r
+ if(strchr(dirs,'8')) Type = 8;\r
+ if(strchr(dirs,'9')) Type = 9;\r
+ }\r
+ else\r
+ {\r
+ if(strchr(dirs,'1')) return;\r
+ if(strchr(dirs,'3')) Type = 1;\r
+ if(strchr(dirs,'5')) Type = 2;\r
+ }\r
long nx=d->nx,ny=d->ny,nz=d->nz;\r
// if(Type == SMOOTH_NONE) return;\r
long p[3]={nx,ny,Type};\r
//-----------------------------------------------------------------------------\r
MGL_NO_EXPORT void *mgl_difr(void *par)\r
{\r
+#if !defined(_MSC_VER) // MSVC produce internal compiler error on this code\r
mglThreadC *t=(mglThreadC *)par;\r
long n=t->p[0], st=t->p[1], bord=t->p[3], nn=t->n;\r
dual *b=t->a, q = *(t->b);\r
mgl_difr_grid(b + ((i%st)+n*(i/st)), n,st, q, bord,tmp,3);\r
delete []tmp;\r
}\r
+#endif\r
return 0;\r
}\r
void MGL_EXPORT mgl_datac_diffr(HADT d, const char *how, mreal q)\r
{\r
if(NX<1 || NY <1 || NZ<1) return;\r
mgl_datac_create(d, NX,NY,NZ);\r
- long nb = strlen(buf);\r
- register long i=0, j=0;\r
const std::string loc = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C");\r
- while(j<nb)\r
+ std::vector<char *> lines;\r
+ std::vector<std::vector<dual> > numbs;\r
+ lines.push_back(buf);\r
+ for(char *s=buf; *s; s++) if(isn(*s))\r
+ { lines.push_back(s+1); *s = 0; s++; }\r
+ numbs.resize(lines.size());\r
+ long nl = long(lines.size());\r
+//#pragma omp parallel for\r
+ for(long k=0;k<nl;k++)\r
{\r
- while(j<nb && buf[j]<=' ') j++;\r
- while(buf[j]=='#') // skip comment\r
+ char *b = lines[k];\r
+ long nb = strlen(b);\r
+ register long i=0, j=0;\r
+\r
+ while(j<nb)\r
{\r
- if(i>0 || buf[j+1]!='#') // this is columns id\r
- while(j<nb && !isn(buf[j])) j++;\r
+ while(j<nb && b[j]<=' ') j++;\r
+ if(j>=nb) break;\r
+ while(b[j]=='#') // skip comment\r
+ {\r
+ if(i>0 || b[j+1]!='#') // this is columns id\r
+ while(j<nb && !isn(b[j])) j++;\r
+ else // NOTE I suppose that only single line contain column ids\r
+ {\r
+ while(j<nb && !isn(b[j]))\r
+ {\r
+ if(b[j]>='a' && b[j]<='z') d->id.push_back(b[j]);\r
+ j++;\r
+ }\r
+ }\r
+ while(j<nb && b[j]<=' ') j++;\r
+ }\r
+ char *s=b+j;\r
+ register long sk=0;\r
+ while(j<nb && b[j]>' ' && ((b[j]!=',' && b[j]!=' ') || sk!=0) && b[j]!=';')\r
+ {\r
+ if(strchr("[{(",b[j])) sk++;\r
+ if(strchr("]})",b[j])) sk--;\r
+ j++;\r
+ }\r
+ b[j]=0;\r
+ double re=0,im=0; size_t ll=strlen(s);\r
+ while(s[ll]<=' ') ll--;\r
+ if(*s=='(') sscanf(s,"(%lg,%lg)",&re,&im);\r
+ else if(*s=='i') { re=0; im=atof(s+1); }\r
+ else if(*s=='[') sscanf(s,"[%lg,%lg]",&re,&im);\r
+ else if(*s=='{') sscanf(s,"{%lg,%lg}",&re,&im);\r
+ else if(s[ll]=='i')\r
+ {\r
+ double a,b; s[ll] = 0;\r
+ int s1=sscanf(s,"%lg+%lg",&re,&im);\r
+ int s2=sscanf(s,"%lg-%lg",&a,&b);\r
+ if(s1<2)\r
+ {\r
+ if(s2==2) { re=a; im=-b; }\r
+ else { im=atof(s); re=0; }\r
+ }\r
+ }\r
else\r
{\r
- while(j<nb && !isn(buf[j]))\r
+ double a,b;\r
+ int s1=sscanf(s,"%lg+i%lg",&re,&im);\r
+ int s2=sscanf(s,"%lg-i%lg",&a,&b);\r
+ if(s1<2)\r
{\r
- if(buf[j]>='a' && buf[j]<='z')\r
- d->id.push_back(buf[j]);\r
- j++;\r
+ if(s2==2) { re=a; im=-b; }\r
+ else { re=atof(s); im=0; }\r
}\r
}\r
- while(j<nb && buf[j]<=' ') j++;\r
- }\r
- char *s=buf+j;\r
- while(j<nb && buf[j]>=' ' && buf[j]!=';') j++;\r
- buf[j]=0;\r
- double re=0,im=0; size_t ll=strlen(s);\r
- while(s[ll]<=' ') ll--;\r
- if(*s=='(') sscanf(s,"(%lg,%lg)",&re,&im);\r
- else if(*s=='[') sscanf(s,"[%lg,%lg]",&re,&im);\r
- else if(*s=='{') sscanf(s,"{%lg,%lg}",&re,&im);\r
- else if(s[ll]=='i')\r
- {\r
- double a,b; s[ll] = 0;\r
- int s1=sscanf(s,"%lg+%lg",&re,&im);\r
- int s2=sscanf(s,"%lg-%lg",&a,&b);\r
- if(s2==2 && s1<2) { re=a; im=-b; }\r
-\r
+ numbs[k].push_back(dual(re,im));\r
}\r
- else\r
- {\r
- double a,b;\r
- int s1=sscanf(s,"%lg+i%lg",&re,&im);\r
- int s2=sscanf(s,"%lg-i%lg",&a,&b);\r
- if(s2==2 && s1<2) { re=a; im=-b; }\r
- }\r
- d->a[i] = dual(re,im);\r
- i++; if(i>=NX*NY*NZ) break;\r
+ }\r
+ register long i=0, n=NX*NY*NZ;\r
+ for(long k=0;k<nl && i<n;k++)\r
+ {\r
+ std::vector<dual> &vals = numbs[k];\r
+ long c = vals.size();\r
+ if(c>n-i) c = n-i;\r
+ memcpy(d->a+i,&(vals[0]),c*sizeof(dual));\r
+ i += c;\r
}\r
setlocale(LC_NUMERIC, loc.c_str());\r
}\r
//-----------------------------------------------------------------------------\r
int MGL_EXPORT mgl_datac_read(HADT d, const char *fname)\r
{\r
- long l=1,m=1,k=1;\r
+ long l=1,m=1,k=1,sk=0;\r
long nb,i;\r
gzFile fp = gzopen(fname,"r");\r
if(!fp)\r
bool first=false; // space is not allowed delimiter for file with complex numbers\r
register char ch;\r
for(i=nb-1;i>=0;i--) if(buf[i]>' ') break;\r
- buf[i+1]=0; nb = i; // remove tailing spaces\r
+ buf[i+1]=0; nb = i+1; // remove tailing spaces\r
for(i=0;i<nb-1 && !isn(buf[i]);i++) // determine nx\r
{\r
while(buf[i]=='#') { while(!isn(buf[i]) && i<nb) i++; }\r
ch = buf[i];\r
if(ch>' ' && !first) first=true;\r
- if(first && (ch=='\t' || ch==';') && buf[i+1]!='\t') k++; // ',' is not valid delimiter for complex arrays\r
+ if(strchr("[{(",ch)) sk++;\r
+ if(strchr("]})",ch)) sk--;\r
+ if(first && buf[i+1]>' ' && (ch=='\t' || ch==';' || ((ch==' '||ch==',') && sk==0) )) k++;\r
}\r
first = false;\r
for(i=0;i<nb-1;i++) // determine ny\r
void MGL_EXPORT mgl_datac_modify_vw(HADT d, const char *eq,HCDT vdat,HCDT wdat)\r
{\r
std::wstring s = d->s; d->s = L"u";\r
- mglDataV x(d->nx,d->ny,d->nz); x.Fill(0,1,'x'); x.s=L"x";\r
- mglDataV y(d->nx,d->ny,d->nz); y.Fill(0,1,'y'); y.s=L"y";\r
- mglDataV z(d->nx,d->ny,d->nz); z.Fill(0,1,'z'); z.s=L"z";\r
+ mglDataV x(d->nx,d->ny,d->nz, 0,1,'x'); x.s=L"x";\r
+ mglDataV y(d->nx,d->ny,d->nz, 0,1,'y'); y.s=L"y";\r
+ mglDataV z(d->nx,d->ny,d->nz, 0,1,'z'); z.s=L"z";\r
+ mglDataV i(d->nx,d->ny,d->nz, 0,d->nx-1,'x'); i.s=L"i";\r
+ mglDataV j(d->nx,d->ny,d->nz, 0,d->ny-1,'y'); j.s=L"j";\r
+ mglDataV k(d->nx,d->ny,d->nz, 0,d->nz-1,'z'); k.s=L"k";\r
mglDataV r(d->nx,d->ny,d->nz); r.s=L"#$mgl";\r
mglData v(vdat), w(wdat); v.s = L"v"; w.s = L"w";\r
std::vector<mglDataA*> list;\r
list.push_back(&x); list.push_back(&y); list.push_back(&z); list.push_back(d);\r
list.push_back(&v); list.push_back(&w); list.push_back(&r);\r
+ list.push_back(&i); list.push_back(&j); list.push_back(&k);\r
d->Set(mglFormulaCalcC(eq,list)); d->s = s;\r
}\r
void MGL_EXPORT mgl_datac_modify_vw_(uintptr_t *d, const char *eq, uintptr_t *v, uintptr_t *w,int l)\r
char *fname = new char[n];\r
\r
//read first file\r
- do{ snprintf(fname,n,templ,t); t+= step; } while(!mgl_datac_read(&d,fname) && t<=to);\r
+ do{ snprintf(fname,n,templ,t); fname[n-1]=0; t+= step; } while(!mgl_datac_read(&d,fname) && t<=to);\r
\r
if(t>to) { delete []fname; return false; }\r
kx = d.nx; ky = d.ny; kz = d.nz;\r
// read other files\r
for(;t<=to;t+=step)\r
{\r
- snprintf(fname,n,templ,t);\r
+ snprintf(fname,n,templ,t); fname[n-1]=0;\r
if(mgl_datac_read(&d,fname))\r
if(!mgl_add_file(kx,ky,kz,b,&d,as_slice))\r
{ delete []fname; free(b); return false; }\r
// draw it\r
bool b1d2 = a->v(i+1,j,ak)>v2 && a->v(i,j-1,ak)>v2;\r
bool b2d1 = a->v(i,j,ak)>v2 && a->v(i+1,j-1,ak)>v2;\r
- mreal vv = mgl_data_linear(a,i+0.5,j-0.5,ak);\r
- vv = (vv-v1)*(vv-v2);\r
+// mreal vv = mgl_data_linear(a,i+0.5,j-0.5,ak);\r
+// vv = (vv-v1)*(vv-v2);\r
if(num<3) continue;\r
if(num==4) gr->quad_plot(p[0],p[1],p[3],p[2]);\r
else if(num==3) gr->trig_plot(p[0],p[1],p[2]);\r
long nx=t->p[0], kind=t->p[2];\r
mreal *b=t->a, delta=t->c[0];\r
const mreal *a=t->b;\r
- if(kind==SMOOTH_LINE_3)\r
+ if(kind>0)\r
#if !MGL_HAVE_PTHREAD\r
#pragma omp parallel for\r
#endif\r
for(long i=t->id;i<t->n;i+=mglNumThr)\r
{\r
register long j = i%nx;\r
- if(j>0 && j<nx-1) b[i] = (a[i-1] + a[i] + a[i+1])/3.;\r
- else b[i] = a[i];\r
- }\r
- else if(kind==SMOOTH_LINE_5)\r
-#if !MGL_HAVE_PTHREAD\r
-#pragma omp parallel for\r
-#endif\r
- for(long i=t->id;i<t->n;i+=mglNumThr)\r
- {\r
- register long j = i%nx;\r
- if(j>1 && j<nx-2) b[i] = (a[i-2] + a[i-1] + a[i] + a[i+1] + a[i+2])/5.;\r
- else if(j==1 || j==nx-2) b[i] = (a[i-1] + a[i] + a[i+1])/3.;\r
- else b[i] = a[i];\r
+ if(j-kind<0) j = i+kind-j;\r
+ else if(j+kind>nx-1) j = i+nx-1-j-kind;\r
+ else j=i;\r
+ for(long k=-kind;k<=kind;k++) b[i] += a[j+k]/(2*kind+1);\r
}\r
- else if(kind==SMOOTH_QUAD_5)\r
+ else\r
#if !MGL_HAVE_PTHREAD\r
#pragma omp parallel for\r
#endif\r
#pragma omp parallel for\r
#endif\r
for(long i=t->id;i<t->n;i+=mglNumThr)\r
- b[i] = mgl_max(a[i]-delta,mgl_min(a[i]+delta,b[i]));\r
- return 0;\r
+ {\r
+ double ab = fabs(a[i]-b[i]);\r
+ if(ab>delta) b[i] = a[i]+(delta/ab)*(b[i]-a[i]);\r
+ }\r
+ return 0;\r
}\r
MGL_NO_EXPORT void *mgl_smth_y(void *par)\r
{\r
long nx=t->p[0],ny=t->p[1], kind=t->p[2];\r
mreal *b=t->a, delta=t->c[0];\r
const mreal *a=t->b;\r
- if(kind==SMOOTH_LINE_3)\r
+ if(kind>0)\r
#if !MGL_HAVE_PTHREAD\r
#pragma omp parallel for\r
#endif\r
for(long i=t->id;i<t->n;i+=mglNumThr)\r
{\r
register long j = (i/nx)%ny;\r
- if(j>0 && j<ny-1) b[i] = (a[i-nx] + a[i] + a[i+nx])/3.;\r
- else b[i] = a[i];\r
- }\r
- else if(kind==SMOOTH_LINE_5)\r
-#if !MGL_HAVE_PTHREAD\r
-#pragma omp parallel for\r
-#endif\r
- for(long i=t->id;i<t->n;i+=mglNumThr)\r
- {\r
- register long j = (i/nx)%ny;\r
- if(j>1 && j<ny-2) b[i] = (a[i-2*nx] + a[i-nx] + a[i] + a[i+nx] + a[i+2*nx])/5.;\r
- else if(j==1 || j==ny-2) b[i] = (a[i-nx] + a[i] + a[i+nx])/3.;\r
- else b[i] = a[i];\r
+ if(j-kind<0) j = i+(kind-j)*nx;\r
+ else if(j+kind>ny-1) j = i+(ny-1-j-kind)*nx;\r
+ else j=i;\r
+ for(long k=-kind;k<=kind;k++) b[i] += a[j+k*nx]/(2*kind+1);\r
}\r
- else if(kind==SMOOTH_QUAD_5)\r
+ else\r
#if !MGL_HAVE_PTHREAD\r
#pragma omp parallel for\r
#endif\r
#pragma omp parallel for\r
#endif\r
for(long i=t->id;i<t->n;i+=mglNumThr)\r
- b[i] = mgl_max(a[i]-delta,mgl_min(a[i]+delta,b[i]));\r
- return 0;\r
+ {\r
+ double ab = fabs(a[i]-b[i]);\r
+ if(ab>delta) b[i] = a[i]+(delta/ab)*(b[i]-a[i]);\r
+ }\r
+ return 0;\r
}\r
MGL_NO_EXPORT void *mgl_smth_z(void *par)\r
{\r
register long nn=t->p[0]*t->p[1], nz=t->n/nn, kind=t->p[2];\r
mreal *b=t->a, delta=t->c[0];\r
const mreal *a=t->b;\r
- if(kind==SMOOTH_LINE_3)\r
+ if(kind>1)\r
#if !MGL_HAVE_PTHREAD\r
#pragma omp parallel for\r
#endif\r
for(long i=t->id;i<t->n;i+=mglNumThr)\r
{\r
register long j = i/nn;\r
- if(j>0 && j<nz-1) b[i] = (a[i-nn] + a[i] + a[i+nn])/3.;\r
- else b[i] = a[i];\r
+ if(j-kind<0) j = i+(kind-j)*nn;\r
+ else if(j+kind>nz-1) j = i+(nz-1-j-kind)*nn;\r
+ else j=i;\r
+ for(long k=-kind;k<=kind;k++) b[i] += a[j+k*nn]/(2*kind+1);\r
}\r
- else if(kind==SMOOTH_LINE_5)\r
-#if !MGL_HAVE_PTHREAD\r
-#pragma omp parallel for\r
-#endif\r
- for(long i=t->id;i<t->n;i+=mglNumThr)\r
- {\r
- register long j = i/nn;\r
- if(j>1 && j<nz-2) b[i] = (a[i-2*nn] + a[i-nn] + a[i] + a[i+nn] + a[i+2*nn])/5.;\r
- else if(j==1 || j==nz-2) b[i] = (a[i-nn] + a[i] + a[i+nn])/3.;\r
- else b[i] = a[i];\r
- }\r
- else if(kind==SMOOTH_QUAD_5)\r
+ else\r
#if !MGL_HAVE_PTHREAD\r
#pragma omp parallel for\r
#endif\r
#pragma omp parallel for\r
#endif\r
for(long i=t->id;i<t->n;i+=mglNumThr)\r
- b[i] = mgl_max(a[i]-delta,mgl_min(a[i]+delta,b[i]));\r
+ {\r
+ double ab = fabs(a[i]-b[i]);\r
+ if(ab>delta) b[i] = a[i]+(delta/ab)*(b[i]-a[i]);\r
+ }\r
return 0;\r
}\r
void MGL_EXPORT mgl_data_smooth(HMDT d, const char *dirs, mreal delta)\r
{\r
- long Type = SMOOTH_QUAD_5;\r
+ long Type = -1;\r
if(!dirs || *dirs==0) dirs = "xyz";\r
- if(strchr(dirs,'0') || strchr(dirs,'1')) return;\r
- if(strchr(dirs,'3')) Type = SMOOTH_LINE_3;\r
- if(strchr(dirs,'5')) Type = SMOOTH_LINE_5;\r
+ if(strchr(dirs,'0')) return;\r
+ if(strchr(dirs,'d'))\r
+ {\r
+ if(strchr(dirs,'1')) Type = 1;\r
+ if(strchr(dirs,'2')) Type = 2;\r
+ if(strchr(dirs,'3')) Type = 3;\r
+ if(strchr(dirs,'4')) Type = 4;\r
+ if(strchr(dirs,'5')) Type = 5;\r
+ if(strchr(dirs,'6')) Type = 6;\r
+ if(strchr(dirs,'7')) Type = 7;\r
+ if(strchr(dirs,'8')) Type = 8;\r
+ if(strchr(dirs,'9')) Type = 9;\r
+ }\r
+ else\r
+ {\r
+ if(strchr(dirs,'1')) return;\r
+ if(strchr(dirs,'3')) Type = 1;\r
+ if(strchr(dirs,'5')) Type = 2;\r
+ }\r
long nx=d->nx,ny=d->ny,nz=d->nz;\r
// if(Type == SMOOTH_NONE) return;\r
long p[3]={nx,ny,Type};\r
{\r
static char buf[512];\r
char s[128]; buf[0]=0;\r
- snprintf(s,128,"nx = %ld\tny = %ld\tnz = %ld\n",d->GetNx(),d->GetNy(),d->GetNz()); strcat(buf,s);\r
+ snprintf(s,128,"nx = %ld\tny = %ld\tnz = %ld\n",d->GetNx(),d->GetNy(),d->GetNz());\r
+ s[127]=0; strcat(buf,s);\r
\r
long i=0,j=0,k=0;\r
mreal A=0,Wa=0,X=0,Y=0,Z=0,Wx=0,Wy=0,Wz=0, b;\r
b = mgl_data_max_int(d,&i,&j,&k);\r
- snprintf(s,128,"Maximum is %g\t at x = %ld\ty = %ld\tz = %ld\n", b,i,j,k); strcat(buf,s);\r
+ snprintf(s,128,"Maximum is %g\t at x = %ld\ty = %ld\tz = %ld\n", b,i,j,k);\r
+ s[127]=0; strcat(buf,s);\r
b = mgl_data_min_int(d,&i,&j,&k);\r
- snprintf(s,128,"Minimum is %g\t at x = %ld\ty = %ld\tz = %ld\n", b,i,j,k); strcat(buf,s);\r
+ snprintf(s,128,"Minimum is %g\t at x = %ld\ty = %ld\tz = %ld\n", b,i,j,k);\r
+ s[127]=0; strcat(buf,s);\r
\r
mgl_data_momentum_val(d,'a',&A,&Wa,0,0); mgl_data_momentum_val(d,'x',&X,&Wx,0,0);\r
mgl_data_momentum_val(d,'y',&Y,&Wy,0,0); mgl_data_momentum_val(d,'z',&Z,&Wz,0,0);\r
- snprintf(s,128,"Averages are:\n<a> = %g\t<x> = %g\t<y> = %g\t<z> = %g\n", A,X,Y,Z); strcat(buf,s);\r
- snprintf(s,128,"Widths are:\nWa = %g\tWx = %g\tWy = %g\tWz = %g\n", Wa,Wx,Wy,Wz); strcat(buf,s);\r
+ snprintf(s,128,"Averages are:\n<a> = %g\t<x> = %g\t<y> = %g\t<z> = %g\n", A,X,Y,Z);\r
+ s[127]=0; strcat(buf,s);\r
+ snprintf(s,128,"Widths are:\nWa = %g\tWx = %g\tWy = %g\tWz = %g\n", Wa,Wx,Wy,Wz);\r
+ s[127]=0; strcat(buf,s);\r
return buf;\r
}\r
int MGL_EXPORT mgl_data_info_(uintptr_t *d, char *out, int len)\r
xx1=mgl_max(xx1,0); xx2=mgl_min(xx2,nx-1);\r
yy1=mgl_max(yy1,0); yy2=mgl_min(yy2,ny-1);\r
if(xx1>xx2 || yy1>yy2) continue;\r
- \r
+\r
mreal d1x = vx1-vx0, d1y = vy1-vy0;\r
mreal d2x = vx2-vx0, d2y = vy2-vy0;\r
mreal d3x = vx3+vx0-vx1-vx2, d3y = vy3+vy0-vy1-vy2;\r
mglData *b=new mglData(n);\r
mreal v[2]={v1,v2};\r
long nx=dat->GetNx(), ny=dat->GetNy(), nz=dat->GetNz();\r
- long ns=abs(nsub)+1, p[5]={n,ns,nx,ny,nz};\r
+ long ns=labs(nsub)+1, p[5]={n,ns,nx,ny,nz};\r
if(nsub==0) mglStartThread(mgl_hist_1,mgl_hist_p, nx*ny*nz, b->a,(const mreal *)dat,0,p,v);\r
else mglStartThread(mgl_hist_2,mgl_hist_p, nx*ny*nz*ns*ns*ns, b->a,(const mreal *)dat,0,p,v);\r
return b;\r
mreal v[2]={v1,v2};\r
\r
long nx=dat->GetNx(), ny=dat->GetNy(), nz=dat->GetNz();\r
- long ns=abs(nsub)+1, p[5]={n,ns,nx,ny,nz};\r
+ long ns=labs(nsub)+1, p[5]={n,ns,nx,ny,nz};\r
if(nsub==0) mglStartThread(mgl_hist_1,mgl_hist_p, nx*ny*nz, b->a,(const mreal *)dat,(const mreal *)weight,p,v);\r
else mglStartThread(mgl_hist_2,mgl_hist_p, nx*ny*nz*ns*ns*ns, b->a,(const mreal *)dat,(const mreal *)weight,p,v);\r
return b;\r
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<mglDataA*> 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();
}
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<mglDataA*> 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();
}
void MGL_EXPORT mgl_delete_data_(uintptr_t *d)\r
{ if(_DT_) delete _DT_; }\r
//-----------------------------------------------------------------------------\r
-void mglFromStr(HMDT d,char *buf,long NX,long NY,long NZ) // TODO: add multithreading read\r
+void mglFromStr(HMDT d,char *buf,long NX,long NY,long NZ)\r
{\r
if(NX<1 || NY <1 || NZ<1) return;\r
mgl_data_create(d, NX,NY,NZ);\r
- long nb = strlen(buf);\r
- register long i=0, j=0;\r
const std::string loc = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C");\r
- while(j<nb)\r
+ std::vector<char *> lines;\r
+ std::vector<std::vector<mreal> > numbs;\r
+ lines.push_back(buf);\r
+ for(char *s=buf; *s; s++) if(isn(*s))\r
+ { lines.push_back(s+1); *s = 0; s++; }\r
+ numbs.resize(lines.size());\r
+ long nl = long(lines.size());\r
+#pragma omp parallel for\r
+ for(long k=0;k<nl;k++)\r
{\r
- while(j<nb && buf[j]<=' ') j++;\r
- while(buf[j]=='#') // skip comment\r
+ char *b = lines[k];\r
+ long nb = strlen(b);\r
+ register long i=0, j=0;\r
+ while(j<nb)\r
{\r
- if(i>0 || buf[j+1]!='#') // this is columns id\r
- while(j<nb && !isn(buf[j])) j++;\r
- else\r
+ while(j<nb && b[j]<=' ') j++;\r
+ if(j>=nb) break;\r
+ while(b[j]=='#') // skip comment\r
{\r
- while(j<nb && !isn(buf[j]))\r
+ if(i>0 || b[j+1]!='#') // this is columns id\r
+ while(j<nb && !isn(b[j])) j++;\r
+ else // NOTE I suppose that only single line contain column ids\r
{\r
- if(buf[j]>='a' && buf[j]<='z')\r
- d->id.push_back(buf[j]);\r
- j++;\r
+ while(j<nb && !isn(b[j]))\r
+ {\r
+ if(b[j]>='a' && b[j]<='z')\r
+ d->id.push_back(b[j]);\r
+ j++;\r
+ }\r
}\r
+ while(j<nb && b[j]<=' ') j++;\r
}\r
- while(j<nb && buf[j]<=' ') j++;\r
+ char *s=b+j;\r
+ while(j<nb && b[j]>' ' && b[j]!=',' && b[j]!=';') j++;\r
+ b[j]=0;\r
+ numbs[k].push_back(strstr(s,"NAN")?NAN:atof(s));\r
}\r
- char *s=buf+j;\r
- while(j<nb && buf[j]>' ' && buf[j]!=',' && buf[j]!=';') j++;\r
- buf[j]=0;\r
- d->a[i] = strstr(s,"NAN")?NAN:atof(s);\r
- i++; if(i>=NX*NY*NZ) break;\r
+ }\r
+ register long i=0, n=NX*NY*NZ;\r
+ for(long k=0;k<nl && i<n;k++)\r
+ {\r
+ std::vector<mreal> &vals = numbs[k];\r
+ long c = vals.size();\r
+ if(c>n-i) c = n-i;\r
+ memcpy(d->a+i,&(vals[0]),c*sizeof(mreal));\r
+ i += c;\r
}\r
setlocale(LC_NUMERIC, loc.c_str());\r
}\r
bool first=false;\r
register char ch;\r
for(i=nb-1;i>=0;i--) if(buf[i]>' ') break;\r
- buf[i+1]=0; nb = i; // remove tailing spaces\r
+ buf[i+1]=0; nb = i+1; // remove tailing spaces\r
for(i=0;i<nb-1 && !isn(buf[i]);i++) // determine nx\r
{\r
while(buf[i]=='#') { while(!isn(buf[i]) && i<nb) i++; }\r
mglDataV x(d->nx,d->ny,d->nz, 0,1,'x'); x.s=L"x";\r
mglDataV y(d->nx,d->ny,d->nz, 0,1,'y'); y.s=L"y";\r
mglDataV z(d->nx,d->ny,d->nz, 0,1,'z'); z.s=L"z";\r
+ mglDataV i(d->nx,d->ny,d->nz, 0,d->nx-1,'x'); i.s=L"i";\r
+ mglDataV j(d->nx,d->ny,d->nz, 0,d->ny-1,'y'); j.s=L"j";\r
+ mglDataV k(d->nx,d->ny,d->nz, 0,d->nz-1,'z'); k.s=L"k";\r
mglDataV r(d->nx,d->ny,d->nz); r.s=L"#$mgl";\r
mglData v(vdat), w(wdat); v.s = L"v"; w.s = L"w";\r
std::vector<mglDataA*> list;\r
list.push_back(&x); list.push_back(&y); list.push_back(&z); list.push_back(d);\r
list.push_back(&v); list.push_back(&w); list.push_back(&r);\r
+ list.push_back(&i); list.push_back(&j); list.push_back(&k);\r
d->Set(mglFormulaCalc(eq,list)); d->s = s;\r
}\r
void MGL_EXPORT mgl_data_modify_vw_(uintptr_t *d, const char *eq, uintptr_t *v, uintptr_t *w,int l)\r
char *fname = new char[n];\r
\r
//read first file\r
- do{ snprintf(fname,n,templ,t); t+= step; } while(!mgl_data_read(&d,fname) && t<=to);\r
+ do{ snprintf(fname,n,templ,t); fname[n-1]=0; t+= step; } while(!mgl_data_read(&d,fname) && t<=to);\r
\r
if(t>to) { delete []fname; return false; }\r
kx = d.nx; ky = d.ny; kz = d.nz;\r
// read other files\r
for(;t<=to;t+=step)\r
{\r
- snprintf(fname,n,templ,t);\r
+ snprintf(fname,n,templ,t); fname[n-1]=0;\r
if(mgl_data_read(&d,fname))\r
if(!mgl_add_file(kx,ky,kz,b,&d,as_slice))\r
{ delete []fname; free(b); return false; }\r
//-----------------------------------------------------------------------------\r
size_t MGL_LOCAL_PURE mgl_col_dif(unsigned char *c1,unsigned char *c2,bool sum)\r
{\r
- size_t res,d1=abs(long(c1[0])-long(c2[0])),\r
- d2=abs(long(c1[1])-long(c2[1])),d3=abs(long(c1[2])-long(c2[2]));\r
+ size_t res,d1=labs(long(c1[0])-long(c2[0])),\r
+ d2=labs(long(c1[1])-long(c2[1])),d3=labs(long(c1[2])-long(c2[2]));\r
if(sum) res = d1+d2+d3;\r
else res = mgl_max(d1,mgl_max(d2,d3));\r
return res;\r
if(!strcmp(fname+len-4,".bmp")) mgl_bmp_save(fname, nx,ny,p);\r
if(!strcmp(fname+len-4,".png")) mgl_png_save(fname, nx,ny,p);\r
if(!strcmp(fname+len-4,".eps") || !strcmp(fname+len-4,".bps")) mgl_bps_save(fname, nx,ny,p);\r
+ delete []p; delete []d;\r
}\r
//-----------------------------------------------------------------------------\r
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)\r
***************************************************************************/
#include <time.h>
#include <ctype.h>
+#include "mgl2/base.h"
#include "mgl2/parser.h"
#if MGL_HAVE_GSL
#include <gsl/gsl_sf.h>
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;i<res.GetNN();i++) res.a[i] = mgl_rnd();
else if(!str.compare(L"nan")) res = NAN;
else if(!str.compare(L"pi")) res = M_PI;
else if(!str.compare(L"on")) res = 1;
else if(!str.compare(L"off")) res = 0;
+/* else if(!str.compare(L"t")) res.Fill(0,1,'x');
+ else if(!str.compare(L"x") && arg && arg->curGr)
+ {
+ 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;
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;i<res.GetNN();i++) res.a[i] = mgl_rnd();
else if(!str.compare(L"nan")) res = mreal(NAN);
else if(!str.compare(L"pi")) res = mreal(M_PI);
else if(!str.compare(L"on")) res = mreal(1.);
else if(!str.compare(L"off")) res = mreal(0.);
+/* else if(!str.compare(L"t")) res.Fill(0,1,'x');
+ else if(!str.compare(L"x") && arg && arg->curGr)
+ 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
int res=0;
bool rr=true;
mglData *d = dynamic_cast<mglData *>(a[0].d);
+ mglData *f = dynamic_cast<mglData *>(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;
}
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;
}
//-----------------------------------------------------------------------------
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;
}
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;
}
{"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},
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);
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;
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;
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);
{
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);
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);
#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;
}
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();
}
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");
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);
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);
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;
}\r
else // glyph_wire(p,f,g, d);\r
{\r
+ long il=0;\r
for(long ik=0;ik<g.nl;ik++)\r
{\r
- long il=0;\r
x = g.line[2*ik]; y = g.line[2*ik+1];\r
if(x==0x3fff && y==0x3fff) // line breakthrough\r
{ il = ik+1; continue; }\r
#pragma omp parallel
#endif
{
- void *w = mgl_fft_alloc_thr(nx);
+ void *w = mgl_fft_alloc_thr(ny);
#pragma omp for nowait
for(long i=t->id;i<t->n;i+=mglNumThr)
mgl_fft(t->b+2*(i%nx)+2*nx*ny*(i/nx), nx, ny, t->v, w, t->p[3]);
#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;i<t->n;i+=mglNumThr)
mgl_fft(t->b+2*i, nx*ny, nz, t->v, w, t->p[3]);
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;i<n;i++)
- aa[i] = xx ? gsl_dht_x_sample(dht, i) : gsl_dht_k_sample(dht, i);
+ aa[i*dn] = kk ? gsl_dht_k_sample(dht, i) : gsl_dht_x_sample(dht, i);
gsl_dht_free(dht);
#endif
}
else // Fourier
{
- if(xx) for(long i=0;i<n;i++) aa[i] = mreal(2*i-n)/n;
- else for(long i=0;i<n;i++) aa[i] = M_PI*(i<n/2 ? i:i-n);
+ if(kk) for(long i=0;i<n;i++) aa[i*dn] = M_PI*(i<n/2 ? i:i-n);
+ else for(long i=0;i<n;i++) aa[i*dn] = mreal(2*i-n)/n;
}
#pragma omp parallel for
- for(long i=1;i<d->ny*d->nz;i++) memcpy(aa+i*n,aa,n*sizeof(mreal));
+ for(long i=0;i<d->GetNN();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;
{ 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)
long n = strlen(mglFitRes)+(pre?strlen(pre):0)+1;\r
char *buf = new char[n];\r
if(pre) snprintf(buf,n,"%s%s",pre,mglFitRes);\r
- else strcpy(buf,mglFitRes);\r
- mgl_puts(gr,x,y,z,buf,font,size);\r
+ else strncpy(buf,mglFitRes,n);\r
+ buf[n-1]=0; mgl_puts(gr,x,y,z,buf,font,size);\r
delete []buf;\r
}\r
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)\r
{\r
char buf[32]="";\r
mglFitChi = chi;\r
- snprintf(mglFitRes,1024,"chi=%g",chi);\r
+ snprintf(mglFitRes,1024,"chi=%g",chi); mglFitRes[1023]=0;\r
size_t i,k,len=strlen(var);\r
for(i=0;i<len;i++)\r
{\r
snprintf(buf,32,", %c=%g",var[i],par[i]);\r
- strcat(mglFitRes,buf);\r
+ buf[31]=0; strcat(mglFitRes,buf);\r
}\r
gr->SetWarn(-1,mglFitRes);\r
\r
if(c && (i==0 || !isalnum(eq[i-1])) && (i==len-1 || !isalnum(eq[i+1])))\r
{\r
snprintf(buf,32,"%g",par[c-var]);\r
- strcat(mglFitRes+k, buf); k+=strlen(buf);\r
+ buf[31]=0; strcat(mglFitRes+k, buf); k+=strlen(buf);\r
}\r
else { mglFitRes[k] = eq[i]; k++; }\r
}\r
}\r
Clear(); // first clear old\r
\r
- snprintf(str,256,"%s%c%s.vfm",path,sep,base?base:"");\r
+ snprintf(str,256,"%s%c%s.vfm",path,sep,base?base:""); str[255]=0;\r
std::vector<short> norm, bold, ital, both;\r
if(!(base && *base) || !read_main(str,norm))\r
{\r
//================== bold ===========================================\r
#pragma omp section\r
{ char str[256]; snprintf(str,256,"%s%c%s_b.vfm",path,sep,base); // this file may absent\r
- read_data(str, 1, bold, ex_b); }\r
+ str[255]=0; read_data(str, 1, bold, ex_b); }\r
\r
//================== italic =========================================\r
#pragma omp section\r
{ char str[256]; snprintf(str,256,"%s%c%s_i.vfm",path,sep,base);\r
- read_data(str, 2, ital, ex_i); }\r
+ str[255]=0; read_data(str, 2, ital, ex_i); }\r
\r
//================== bold-italic ====================================\r
#pragma omp section\r
{ char str[256]; snprintf(str,256,"%s%c%s_bi.vfm",path,sep,base);\r
- read_data(str, 3, both, ex_bi); }\r
+ str[255]=0; read_data(str, 3, both, ex_bi); }\r
}\r
\r
// now collect data\r
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;
}
//-----------------------------------------------------------------------------
uintptr_t MGL_EXPORT mgl_create_graph_gl_()\r
{ return uintptr_t(new mglCanvasGL); }\r
//-----------------------------------------------------------------------------\r
-mglCanvasGL::mglCanvasGL() : mglCanvas(1,1) {}\r
+mglCanvasGL::mglCanvasGL() : mglCanvas(1,1) { Clf(); Zoom(0,0,1,1); }\r
//-----------------------------------------------------------------------------\r
mglCanvasGL::~mglCanvasGL(){}\r
//-----------------------------------------------------------------------------\r
gl_clf(Back);\r
}\r
//-----------------------------------------------------------------------------\r
+void mglCanvasGL::Clf(const char *col)\r
+{\r
+ mglCanvas::Clf(col);\r
+ gl_clf(mglColor(BDef[0]/255.,BDef[1]/255.,BDef[2]/255.));\r
+}\r
+//-----------------------------------------------------------------------------\r
void mglCanvasGL::gl_clf(mglColor Back)\r
{\r
if(Back==NC) Back = WC;\r
p = (unsigned char **)malloc(height * sizeof(unsigned char *));\r
f = (unsigned char *) malloc(width*height * sizeof(unsigned char)*d);\r
for(long i=0;i<height;i++) p[i] = f+d*width*(height-1-i);\r
+ glReadBuffer(GL_FRONT);\r
glPixelStorei(GL_PACK_ALIGNMENT, 1);\r
glReadPixels(x, y, width, height, alpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, f);\r
return p;\r
//-----------------------------------------------------------------------------
mglParser::mglParser(bool setsize)
{
- InUse = 1;
+ InUse = 1; curGr = 0;
Skip=Stop=for_br=false;
memset(for_stack,0,40*sizeof(int));
memset(if_stack,0,40*sizeof(int));
{
res = 0;
d = mglFormulaCalc(mgl_trim_ws(s.substr(2)), this, DataList).a[0];
- char buf[32]; snprintf(buf,32,"%g",d); AddParam(nn, buf);
+ char buf[32]; snprintf(buf,32,"%g",d);
+ buf[31] = 0; AddParam(nn, buf);
}
return res+1;
}
int mglParser::Parse(mglGraph *gr, std::wstring str, long pos)
{
if(Stop || gr->NeedStop()) return 0;
+ curGr = gr->Self();
std::wstring arg[1024];
str=mgl_trim_ws(str);
long n,k=0,m=0,mm=0,res;
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)
{
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;
}
static mglMatrix bp;\r
if(Quality==MGL_DRAW_NONE) return;\r
#if MGL_HAVE_PTHREAD\r
+ pthread_mutex_lock(&mutexPrm);\r
+ pthread_mutex_lock(&mutexPnt);\r
pthread_mutex_lock(&mutexClf);\r
#elif MGL_HAVE_OMP\r
omp_set_lock(&lockClf);\r
}\r
#if MGL_HAVE_PTHREAD\r
pthread_mutex_unlock(&mutexClf);\r
+ pthread_mutex_unlock(&mutexPnt);\r
+ pthread_mutex_unlock(&mutexPrm);\r
#elif MGL_HAVE_OMP\r
omp_unset_lock(&lockClf);\r
#endif\r
// register int ii = int(0.5+(i*c+j*s)/pw)%8, jj = int(0.5+(j*c-i*s)/pw)%8;\r
// if(ii<0) ii+=8; if(jj<0) jj+=8;\r
register int ii = int(0.5+(i*c+j*s)/pw)&7, jj = int(0.5+(j*c-i*s)/pw)&7;\r
- return m[jj] & (1<<ii);\r
+ return m[jj] & (1L<<ii);\r
}\r
//-----------------------------------------------------------------------------\r
/* Bilinear interpolation r(u,v) = r0 + (r1-r0)*u + (r2-r0)*v + (r3+r0-r1-r2)*u*v\r
if(u<0) v += u*u;\r
else if(u>dd) v += (u-dd)*(u-dd);\r
if(v>pw*pw) continue;\r
- if(!(pd & ( 1<<long(fmod(pp+u/pw/1.5, 16)) ) )) continue;\r
+ if(!(pd & ( 1L<<long(fmod(pp+u/pw/1.5, 16)) ) )) continue;\r
p = p1+d*(u/dd); col2int(p,r,oi);\r
r[3] = v<(pw-1)*(pw-1)/4 ? 255 : mgl_sline(255,dpw*(sqrt(v)+(1-pw)/2));\r
pnt_plot(i,j,p.z+dz,r,oi);\r
if(u<0) v += u*u;\r
else if(u>dd) v += (u-dd)*(u-dd);\r
if(v>pw*pw) continue;\r
- if(!(pd & (1<<long(fmod(pp+u/pw/1.5, 16))))) continue;\r
+ if(!(pd & (1L<<long(fmod(pp+u/pw/1.5, 16))))) continue;\r
p = p1+d*(u/dd); col2int(p,r,oi);\r
r[3] = v<(pw-1)*(pw-1)/4 ? 255 : mgl_sline(255,dpw*(sqrt(v)+(1-pw)/2));\r
pnt_plot(i,j,p.z+dz,r,oi);\r
else if(u>dd) v += (u-dd)*(u-dd);\r
register float pw=dr->PenWidth, dpw=3;\r
if(dr->ObjId==HighId) { pw *= 2; dpw=2; }\r
- if(v>pw*pw || !(dr->PDef & ( 1<<long(fmod(dr->pPos+u/pw/1.5, 16)) ) )) return;\r
+ if(v>pw*pw || !(dr->PDef & ( 1L<<long(fmod(dr->pPos+u/pw/1.5, 16)) ) )) return;\r
mglPnt p = p1+d*(u/dd);\r
unsigned char r[4];\r
col2int(p,r,dr->ObjId);\r
if(y1->GetNx()!=n || y2->GetNx()!=n)\r
{ gr->SetWarn(mglWarnDim,"Candle"); return; }\r
static int cgid=1; gr->StartGroup("Candle",cgid++);\r
- gr->SaveState(opt); gr->SetPenPal(pen,&pal);\r
- gr->NextColor(pal); gr->Reserve(8*n);\r
+ gr->SaveState(opt); gr->SetPenPal(pen,&pal); gr->Reserve(8*n);\r
bool sh = mglchr(pen,'!');\r
+ bool wire = mglchr(pen,'#');\r
\r
mreal dv=nx>n?1:0;\r
if(mglchr(pen,'<')) dv = 1;\r
if(mglchr(pen,'^')) dv = 0;\r
if(mglchr(pen,'>')) dv = -1;\r
mreal zm = gr->AdjustZMin();\r
+ mreal c1,c2; c2=c1=gr->NextColor(pal);\r
+ bool col2 = (gr->GetNumPal(pal)==2 && !sh);\r
+ if(col2) c2 = gr->NextColor(pal);\r
for(long i=0;i<n;i++)\r
{\r
mreal m1=v1->v(i), m2 = v2->v(i), xx = x->v(i);\r
- mreal d = i<nx-1 ? x->v(i+1)-xx : xx-x->v(i-1);\r
+ mreal d = i<nx-1 ? x->v(i+1)-xx : xx-x->v(i-1), c;\r
mreal x1 = xx + d/2*(dv-gr->BarWidth);\r
mreal x2 = x1 + gr->BarWidth*d; xx = (x1+x2)/2;\r
- mreal c = sh ? gr->NextColor(pal,i):gr->CDef;\r
+ if(sh) c = gr->NextColor(pal,i);\r
+ else if(wire) c = (i>0 && m2>v2->v(i-1))?c2:c1;\r
+ else c = (m1>m2)?c1:c2;\r
long n1 = gr->AddPnt(mglPoint(xx,y1->v(i),zm),c);\r
long n2 = gr->AddPnt(mglPoint(xx,m1,zm),c);\r
gr->line_plot(n1,n2);\r
n4 = gr->AddPnt(mglPoint(x2,m2,zm),c);\r
gr->line_plot(n1,n2); gr->line_plot(n1,n3);\r
gr->line_plot(n4,n2); gr->line_plot(n4,n3);\r
- if(m1>m2) gr->quad_plot(n1,n2,n3,n4);\r
+ if(m1>m2 || (col2 && !wire)) gr->quad_plot(n1,n2,n3,n4);\r
}\r
if(d1) delete y1; if(d2) delete y2;\r
gr->EndGroup();\r
bool wire = mglchr(pen,'#');\r
bool above = mglchr(pen,'a'), fall = mglchr(pen,'f');\r
if(above) fall = false;\r
- mreal c1,c2;\r
mreal *dd=new mreal[n], x0,xp,dv=ny>n?1:0;\r
if(mglchr(pen,'<')) dv = 1;\r
if(mglchr(pen,'^')) dv = 0;\r
for(long j=0;j<m;j++)\r
{\r
if(gr->NeedStop()) break;\r
- c2=c1=gr->NextColor(pal);\r
+ mreal c1,c2; c2=c1=gr->NextColor(pal);\r
if(gr->GetNumPal(pal)==2*m && !sh) c2 = gr->NextColor(pal);\r
long mx = j<v->GetNy() ? j:0, my = j<y->GetNy() ? j:0;\r
xp = x0 = gr->GetOrgX('y');\r
{ gr->SetWarn(mglWarnDim,"OHLC"); return; }\r
gr->SaveState(opt);\r
static int cgid=1; gr->StartGroup("OHLC",cgid++);\r
- mreal dv=nx>n?1:0,dd,vv,x1,x2,cc;\r
+ mreal dv=nx>n?1:0;\r
if(mglchr(pen,'<')) dv = 1;\r
if(mglchr(pen,'^')) dv = 0;\r
if(mglchr(pen,'>')) dv = -1;\r
for(long j=0;j<m;j++)\r
{\r
if(gr->NeedStop()) break;\r
- cc=gr->NextColor(pal);\r
+ mreal c1,c2; c2=c1=gr->NextColor(pal);\r
+ if(gr->GetNumPal(pal)==2*m && !sh) c2 = gr->NextColor(pal);\r
mx = j<x->GetNy() ? j:0;\r
for(long i=0;i<n;i++)\r
{\r
+ mreal dd,vv,x1,x2;\r
vv = x->v(i,mx); dd = i<nx-1 ? x->v(i+1)-vv : vv-x->v(i-1);\r
x1 = vv + dd/2*(dv-gr->BarWidth); x2 = x1 + gr->BarWidth*dd;\r
x2 = (x2-x1)/m; x1 += j*x2; x2 += x1; vv = (x2+x1)/2;\r
- mreal c = sh ? gr->NextColor(pal,i):cc;\r
+ if(sh) c1=c2=gr->NextColor(pal,i);\r
register long n1,n2;\r
\r
- dd = open->v(i,j);\r
- n1=gr->AddPnt(mglPoint(x1,dd,zVal),c);\r
- n2=gr->AddPnt(mglPoint(vv,dd,zVal),c);\r
- gr->line_plot(n1,n2);\r
dd = close->v(i,j);\r
+ mreal c = (i==0 || dd>=close->v(i-1,j)) ? c1:c2;\r
n1=gr->AddPnt(mglPoint(vv,dd,zVal),c);\r
n2=gr->AddPnt(mglPoint(x2,dd,zVal),c);\r
gr->line_plot(n1,n2);\r
+ dd = open->v(i,j);\r
+ n1=gr->AddPnt(mglPoint(x1,dd,zVal),c);\r
+ n2=gr->AddPnt(mglPoint(vv,dd,zVal),c);\r
+ gr->line_plot(n1,n2);\r
n1=gr->AddPnt(mglPoint(vv,low->v(i,j),zVal),c);\r
n2=gr->AddPnt(mglPoint(vv,high->v(i,j),zVal),c);\r
gr->line_plot(n1,n2);\r
mreal r = gr->SaveState(opt);\r
long n = (mgl_isnan(r) || r<=0) ? 100:long(r+0.5);\r
mglData z(n,n),res;\r
- mglDataV x(n,n); x.Fill(gr->Min.x,gr->Max.x,'x'); x.s=L"x";\r
- mglDataV y(n,n); y.Fill(gr->Min.y,gr->Max.y,'y'); y.s=L"y";\r
+ mglDataV x(n,n,1, gr->Min.x,gr->Max.x,'x'); x.s=L"x";\r
+ mglDataV y(n,n,1, gr->Min.y,gr->Max.y,'y'); y.s=L"y";\r
mglDataV t(n,n); t.s=L"#$mgl";\r
std::vector<mglDataA*> list;\r
list.push_back(&x); list.push_back(&y); list.push_back(&t);\r
mreal r = gr->SaveState(opt);\r
long n = (mgl_isnan(r) || r<=0) ? 100:long(r+0.5);\r
mglData z(n,n), x(n,n), y(n,n), res;\r
- mglDataV u(n,n); u.Fill(0,1,'x'); u.s=L"u";\r
- mglDataV v(n,n); v.Fill(0,1,'y'); v.s=L"v";\r
+ mglDataV u(n,n,1, 0,1,'x'); u.s=L"u";\r
+ mglDataV v(n,n,1, 0,1,'y'); v.s=L"v";\r
mglDataV t(n,n); t.s=L"#$mgl";\r
std::vector<mglDataA*> list;\r
list.push_back(&u); list.push_back(&v); list.push_back(&t);\r
@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}
@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
@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{""})
@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}
+ФÑ\83нкÑ\86ии Ñ\80иÑ\81Ñ\83Ñ\8eÑ\82 candlestick chart в Ñ\82оÑ\87каÑ\85 @var{x}[i]. ÐÑ\82оÑ\82 гÑ\80аÑ\84ик показÑ\8bваеÑ\82 пÑ\80Ñ\8fмоÑ\83голÑ\8cником ("Ñ\81веÑ\87ой") диапазон изменениÑ\8f велиÑ\87инÑ\8b. Ð\9fÑ\80озÑ\80аÑ\87наÑ\8f (белаÑ\8f) Ñ\81веÑ\87а Ñ\81ооÑ\82веÑ\82Ñ\81Ñ\82вÑ\83еÑ\82 Ñ\80оÑ\81Ñ\82Ñ\83 велиÑ\87инÑ\8b @var{v1}[i]<@var{v2}[i], Ñ\87Ñ\91Ñ\80наÑ\8f -- Ñ\83менÑ\8cÑ\88ениÑ\8e. "Тени" показÑ\8bваÑ\8eÑ\82 минималÑ\8cное @var{y1} и макÑ\81ималÑ\8cное @var{y2} знаÑ\87ениÑ\8f. Ð\95Ñ\81ли @var{v2} оÑ\82Ñ\81Ñ\83Ñ\82Ñ\81Ñ\82вÑ\83еÑ\82, Ñ\82о он опÑ\80еделÑ\8fеÑ\82Ñ\81Ñ\8f как @var{v2}[i]=@var{v1}[i+1]. Ð\9cожно иÑ\81полÑ\8cзоваÑ\82Ñ\8c Ñ\80азнÑ\8bе Ñ\86веÑ\82а длÑ\8f Ñ\80аÑ\81Ñ\82Ñ\83Ñ\89иÑ\85 и падаÑ\8eÑ\89иÑ\85 дней еÑ\81ли Ñ\87иÑ\81ло Ñ\83казаннÑ\8bÑ\85 Ñ\86веÑ\82ов Ñ\80авно Ñ\83двоенномÑ\83 Ñ\87иÑ\81лÑ\83 кÑ\80ивÑ\8bÑ\85 длÑ\8f поÑ\81Ñ\82Ñ\80оениÑ\8f. Ð\95Ñ\81ли @var{pen} Ñ\81одеÑ\80жиÑ\82 @samp{#}, Ñ\82о пÑ\80озÑ\80аÑ\87наÑ\8f Ñ\81веÑ\87а бÑ\83деÑ\82 иÑ\81полÑ\8cзована и пÑ\80и 2-Ñ\86веÑ\82ной Ñ\81Ñ\85еме. См. Ñ\82акже @ref{plot}, @ref{bars}, @ref{ohlc}, @ref{barwidth}. @sref{Candle sample}
@end deftypefn
@anchor{ohlc}
@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}
+ФÑ\83нкÑ\86ии Ñ\80иÑ\81Ñ\83Ñ\8eÑ\82 Open-High-Low-Close диагÑ\80аммÑ\83. ÐÑ\82оÑ\82 гÑ\80аÑ\84ик Ñ\81одеÑ\80жиÑ\82 веÑ\80Ñ\82икалÑ\8cнÑ\8bе линии междÑ\83 макÑ\81ималÑ\8cнÑ\8bм @var{h} и минималÑ\8cнÑ\8bм @var{l} знаÑ\87ениÑ\8fми, и гоÑ\80изонÑ\82алÑ\8cнÑ\8bе линии пеÑ\80ед/поÑ\81ле веÑ\80Ñ\82икалÑ\8cной линии длÑ\8f наÑ\87алÑ\8cного @var{o} и конеÑ\87ного @var{c} знаÑ\87ений пÑ\80оÑ\86еÑ\81Ñ\81а (обÑ\8bÑ\87но Ñ\86енÑ\8b). Ð\9cожно иÑ\81полÑ\8cзоваÑ\82Ñ\8c Ñ\80азнÑ\8bе Ñ\86веÑ\82а длÑ\8f Ñ\80аÑ\81Ñ\82Ñ\83Ñ\89иÑ\85 и падаÑ\8eÑ\89иÑ\85 дней еÑ\81ли Ñ\87иÑ\81ло Ñ\83казаннÑ\8bÑ\85 Ñ\86веÑ\82ов Ñ\80авно Ñ\83двоенномÑ\83 Ñ\87иÑ\81лÑ\83 кÑ\80ивÑ\8bÑ\85 длÑ\8f поÑ\81Ñ\82Ñ\80оениÑ\8f. См. Ñ\82акже @ref{candle}, @ref{plot}, @ref{barwidth}. @sref{OHLC sample}
@end deftypefn
@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{""})
<tr><td style="padding-left: 5px;font-size: 110%"> <a target=_blank href="http://groups.google.com/group/mathgl"><b>MathGL</b></a> </td></tr>
</table>
-@comment <hr style="width: 100%; height: 1px;">
-@comment <script type="text/javascript"><!--
-@comment google_ad_client = "ca-pub-1128070552722622";
-@comment /* Vertical small */
-@comment google_ad_slot = "5501954624";
-@comment google_ad_width = 120;
-@comment google_ad_height = 240;
-@comment //-->
-@comment </script>
-@comment <script type="text/javascript"
-@comment src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
-@comment </script>
+<hr style="width: 100%; height: 1px;">
+<script type="text/javascript"><!--
+google_ad_client = "ca-pub-1128070552722622";
+/* Vertical small */
+google_ad_slot = "5501954624";
+google_ad_width = 120;
+google_ad_height = 240;
+//-->
+</script>
+<script type="text/javascript"
+src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
+</script>
</nav>
@end html
@end macro
@macro external {}
@html
-@comment <br><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
-@comment <!-- Ref 728x15 -->
-@comment <ins class="adsbygoogle"
-@comment style="display:inline-block;width:728px;height:15px"
-@comment data-ad-client="ca-pub-1128070552722622"
-@comment data-ad-slot="7008431385"></ins>
-@comment <script>
-@comment (adsbygoogle = window.adsbygoogle || []).push({});
-@comment </script><br>
+<br><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+<!-- Ref 728x15 -->
+<ins class="adsbygoogle"
+style="display:inline-block;width:728px;height:15px"
+data-ad-client="ca-pub-1128070552722622"
+data-ad-slot="7008431385"></ins>
+<script>
+(adsbygoogle = window.adsbygoogle || []).push({});
+</script><br>
@comment
-@comment <script type="text/javascript"><!--
-@comment google_ad_client = "ca-pub-1128070552722622";
-@comment /* 728x90, создано 23.12.09 */
-@comment google_ad_slot = "9958083480";
-@comment google_ad_width = 728;
-@comment google_ad_height = 90;
-@comment //-->
-@comment </script>
-@comment <script type="text/javascript"
-@comment src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
-@comment </script><br/>
+<script type="text/javascript"><!--
+google_ad_client = "ca-pub-1128070552722622";
+/* 728x90, создано 23.12.09 */
+google_ad_slot = "9958083480";
+google_ad_width = 728;
+google_ad_height = 90;
+//-->
+</script>
+<script type="text/javascript"
+src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
+</script><br/>
<footer>
<!--LiveInternet counter--><script type="text/javascript"><!--
document.write("<a href='http://www.liveinternet.ru/click' "+
<tr><td style="padding-left: 5px;font-size: 110%"> <a target=_blank href="http://groups.google.com/group/mathgl"><b>MathGL</b></a> </td></tr>
</table>
-@comment <hr style="width: 100%; height: 1px;">
-@comment <script type="text/javascript"><!--
-@comment google_ad_client = "ca-pub-1128070552722622";
-@comment /* Vertical small */
-@comment google_ad_slot = "5501954624";
-@comment google_ad_width = 120;
-@comment google_ad_height = 240;
-@comment //-->
-@comment </script>
-@comment <script type="text/javascript"
-@comment src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
-@comment </script>
+<hr style="width: 100%; height: 1px;">
+<script type="text/javascript"><!--
+google_ad_client = "ca-pub-1128070552722622";
+/* Vertical small */
+google_ad_slot = "5501954624";
+google_ad_width = 120;
+google_ad_height = 240;
+//-->
+</script>
+<script type="text/javascript"
+src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
+</script>
</nav>
@end html
@end macro
@macro external {}
@html
-@comment <br><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
-@comment <!-- Ref 728x15 -->
-@comment <ins class="adsbygoogle"
-@comment style="display:inline-block;width:728px;height:15px"
-@comment data-ad-client="ca-pub-1128070552722622"
-@comment data-ad-slot="7008431385"></ins>
-@comment <script>
-@comment (adsbygoogle = window.adsbygoogle || []).push({});
-@comment </script><br>
+<br><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+<!-- Ref 728x15 -->
+<ins class="adsbygoogle"
+style="display:inline-block;width:728px;height:15px"
+data-ad-client="ca-pub-1128070552722622"
+data-ad-slot="7008431385"></ins>
+<script>
+(adsbygoogle = window.adsbygoogle || []).push({});
+</script><br>
@comment
-@comment <script type="text/javascript"><!--
-@comment google_ad_client = "ca-pub-1128070552722622";
-@comment /* 728x90, создано 23.12.09 */
-@comment google_ad_slot = "9958083480";
-@comment google_ad_width = 728;
-@comment google_ad_height = 90;
-@comment //-->
-@comment </script>
-@comment <script type="text/javascript"
-@comment src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
-@comment </script><br/>
+<script type="text/javascript"><!--
+google_ad_client = "ca-pub-1128070552722622";
+/* 728x90, создано 23.12.09 */
+google_ad_slot = "9958083480";
+google_ad_width = 728;
+google_ad_height = 90;
+//-->
+</script>
+<script type="text/javascript"
+src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
+</script><br/>
<footer>
<!--LiveInternet counter--><script type="text/javascript"><!--
document.write("<a href='http://www.liveinternet.ru/click' "+
ohlc o h l c
@end verbatim
-@pfig{candle, Example of OHLC()}
+@pfig{ohlc, Example of OHLC()}
@c ------------------------------------------------------------------
@external{}
@verbatim
call 'prepare3d'
light on:alpha on
-subplot 2 2 1:title 'Surf3 plot':rotate 50 60:box
+subplot 2 2 0:title 'Surf3 plot':rotate 50 60:box
surf3 c
subplot 2 2 1:title '"\#" style':rotate 50 60:box
ohlc o h l c
@end verbatim
-@pfig{candle, Example of OHLC()}
+@pfig{ohlc, Example of OHLC()}
@c ------------------------------------------------------------------
@external{}
@verbatim
call 'prepare3d'
light on:alpha on
-subplot 2 2 1:title 'Surf3 plot':rotate 50 60:box
+subplot 2 2 0:title 'Surf3 plot':rotate 50 60:box
surf3 c
subplot 2 2 1:title '"\#" style':rotate 50 60:box
@set VERSION 2.3
-@set MINVER .1
+@set MINVER .2
+2.3.2 Released 2 February 2015
+2.3.1 Released 21 October 2014
+2.3 Released 7 August 2014
+2.2.2.1 Released 19 March 2014
2.2.2 Released 10 March 2014
2.2.1 Released 22 January 2014
2.2 Released 11 November 2013
@strong{Latest news}
@itemize
-@item @emph{20 October 2014.}
-New version (v.@value{VERSION}@value{MINVER}) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are @ref{LaTeX package}, command to load external DLL file (@ref{load}), new primitive (@ref{logo}), improvements for projections, manual rotation angle in @ref{axis} and other minor improvements, which denoted @ref{News, here}.
+@item @emph{2 February 2015.}
+New version (v.@value{VERSION}@value{MINVER}) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are parallelizing of reading data files, updating @ref{LaTeX package}, other minor improvements and bugfixes, which denoted @ref{News, here}.
@item @emph{7 August 2014.}
New version (v.@value{VERSION}) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are many major improvements for both MathGL core and for UDAV, which denoted @ref{News, here}.
@end itemize
@itemize
-@item @strong{20 October 2014.}
+@item @strong{2 February 2015.}
+New version (v.2.3.2) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are minor improvements and bugfixes:
+@itemize @bullet
+@item Update @ref{LaTeX package} (thanks to Diego Sejas Viscarra)
+@item Add reading files with complex numbers by @ref{read} command.
+@item Parallelize reading textual data files.
+@item Add 'i','j','k' variables for data filling (see @ref{fill}).
+@item Add saving images in QMathGL even if corresponding format support is disabled.
+@item Add cmake option MGL_DEF_FONT to change default font name or use built-in one (if MGL_DEF_FONT is empty).
+@item Compatibility changes and bugfixes.
+@end itemize
+
+@item @strong{21 October 2014.}
New version (v.2.3.1) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are minor improvements and bugfixes:
@itemize @bullet
@item Add @ref{LaTeX package} @emph{mglTeX} (author Diego Sejas Viscarra) for making figures directly from MGL script located in LaTeX file.
@item Add MGL command @ref{load} for loading MGL commands from external DLL (or .so) module.
@item Add @ref{logo} function to draw bitmap (logo), which is stretched along whole axis range.
@item Add MGL command @ref{reset} which restore default settings and clear image (i.e. call @code{DefaultPlotParam()}).
-@item Add option @code{value} to @ref{axis} function, which allow to set rotation angle for tick labels.
+@c @item Add option @code{value} to @ref{axis} function, which allow to set rotation angle for tick labels.
@item Change y coordinate at x-z projection.
@item Improve projection of 'unrotatable' objects (like @ref{legend}, @ref{title}, ...).
@item Add projection (@ref{ternary}&8) which is the same as usual (@ref{ternary}&4) but don't print text on projections
@strong{Latest news}
@itemize
-@item @emph{20 October 2014.}
-New version (v.@value{VERSION}@value{MINVER}) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are @ref{LaTeX package}, command to load external DLL file (@ref{load}), new primitive (@ref{logo}), improvements for projections, manual rotation angle in @ref{axis} and other minor improvements, which denoted @ref{News, here}.
+@item @emph{2 February 2015.}
+New version (v.@value{VERSION}@value{MINVER}) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are parallelizing of reading data files, updating @ref{LaTeX package}, other minor improvements and bugfixes, which denoted @ref{News, here}.
@item @emph{7 August 2014.}
New version (v.@value{VERSION}) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are many major improvements for both MathGL core and for UDAV, which denoted @ref{News, here}.
@end itemize
@itemize
-@item @strong{20 October 2014.}
+@item @strong{2 February 2015.}
+New version (v.2.3.2) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are minor improvements and bugfixes:
+@itemize @bullet
+@item Update @ref{LaTeX package} (thanks to Diego Sejas Viscarra)
+@item Add reading files with complex numbers by @ref{read} command.
+@item Parallelize reading textual data files.
+@item Add 'i','j','k' variables for data filling (see @ref{fill}).
+@item Add saving images in QMathGL even if corresponding format support is disabled.
+@item Add cmake option MGL_DEF_FONT to change default font name or use built-in one (if MGL_DEF_FONT is empty).
+@item Compatibility changes and bugfixes.
+@end itemize
+
+@item @strong{21 October 2014.}
New version (v.2.3.1) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are minor improvements and bugfixes:
@itemize @bullet
@item Add @ref{LaTeX package} @emph{mglTeX} (author Diego Sejas Viscarra) for making figures directly from MGL script located in LaTeX file.
@item Add MGL command @ref{load} for loading MGL commands from external DLL (or .so) module.
@item Add @ref{logo} function to draw bitmap (logo), which is stretched along whole axis range.
@item Add MGL command @ref{reset} which restore default settings and clear image (i.e. call @code{DefaultPlotParam()}).
-@item Add option @code{value} to @ref{axis} function, which allow to set rotation angle for tick labels.
+@c @item Add option @code{value} to @ref{axis} function, which allow to set rotation angle for tick labels.
@item Change y coordinate at x-z projection.
@item Improve projection of 'unrotatable' objects (like @ref{legend}, @ref{title}, ...).
@item Add projection (@ref{ternary}&8) which is the same as usual (@ref{ternary}&4) but don't print text on projections
15. Frames by mouse in UDAV ???
A. мысли о frame??? для группы графиков -- не "удалять" их, а запихивать в отдельный кадр -- вопрос что с анимацией???
B. как делать анимацию (кадры) для мышиной версии ... список кадров, кнопки добавить в кадры + вставить из кадра
-16. Docs about mgl_datac_diffr
17. Extend QO + extra docs
18. Import OBJ ???
19. Simplified triangle filling for Quality=1 ?!?
u. Test FlowP + 3d
7. Improve z-order for rapidly oscillating surfaces
-10. Manual rotation angle for axis ticks (as "value" option?!)
-11. Export to XPM (like GIF)
-13. Title and perspective
+8. Manual rotation angle for axis ticks (as "value" option?!)
+9. Export to XPM (like GIF)
+10. Title and perspective
+11. Adjust BarWidth for proper using prevous (i-1) point
+
+12. introduce a set of default arrays like "x", "y", "z" and "t" for MGL ???
+13. Use mgltex.dtx (see e-mail 15 November)
+14. Binary font files for particular platform (+ check ARM). Add utility to translate from current (textual) to binary.
+16. Contour lines above/under surface (e-mail 10.12.14)
+17. Iris plot -- https://en.wikipedia.org/wiki/Iris_flower_data_set
============= DOCUMENTATION =============
C. Translate to Russian everything
D. Docs about JS interface
+1. Docs about new Smooth() styles
+
YY. Sample like http://pyxplot.org.uk/examples/05ap/02hlines/index.html using Stem()
============= UDAV =============
+1. Zoom rectangle after mouse selection
+
2. Create default plot depending on selected row/column/range in data table ?!?
3. Manual data changing should be written into script
CalcDialog::~CalcDialog() {}
void CalcDialog::foc() { text->setFocus(Qt::ActiveWindowFocusReason); }
//-----------------------------------------------------------------------------
-void CalcDialog::key1() { text->setText("1"); foc(); }
-void CalcDialog::key2() { text->setText("2"); foc(); }
-void CalcDialog::key3() { text->setText("3"); foc(); }
-void CalcDialog::key4() { text->setText("4"); foc(); }
-void CalcDialog::key5() { text->setText("5"); foc(); }
-void CalcDialog::key6() { text->setText("6"); foc(); }
-void CalcDialog::key7() { text->setText("7"); foc(); }
-void CalcDialog::key8() { text->setText("8"); foc(); }
-void CalcDialog::key9() { text->setText("9"); foc(); }
-void CalcDialog::key0() { text->setText("0"); foc(); }
-void CalcDialog::keyE() { text->setText("E"); foc(); }
-void CalcDialog::keyPi() { text->setText("pi"); foc(); }
-void CalcDialog::keyX2() { text->setText("^2"); foc(); }
-void CalcDialog::keyAdd() { text->setText("+"); foc(); }
-void CalcDialog::keyMul() { text->setText("*"); foc(); }
-void CalcDialog::keySub() { text->setText("-"); foc(); }
-void CalcDialog::keyDiv() { text->setText("/"); foc(); }
-void CalcDialog::keyBrO() { text->setText("("); foc(); }
-void CalcDialog::keyBrC() { text->setText(")"); foc(); }
-void CalcDialog::keyDot() { text->setText("."); foc(); }
+void CalcDialog::key1() { text->insert("1"); foc(); }
+void CalcDialog::key2() { text->insert("2"); foc(); }
+void CalcDialog::key3() { text->insert("3"); foc(); }
+void CalcDialog::key4() { text->insert("4"); foc(); }
+void CalcDialog::key5() { text->insert("5"); foc(); }
+void CalcDialog::key6() { text->insert("6"); foc(); }
+void CalcDialog::key7() { text->insert("7"); foc(); }
+void CalcDialog::key8() { text->insert("8"); foc(); }
+void CalcDialog::key9() { text->insert("9"); foc(); }
+void CalcDialog::key0() { text->insert("0"); foc(); }
+void CalcDialog::keyE() { text->insert("E"); foc(); }
+void CalcDialog::keyPi() { text->insert("pi"); foc(); }
+void CalcDialog::keyX2() { text->insert("^2"); foc(); }
+void CalcDialog::keyAdd() { text->insert("+"); foc(); }
+void CalcDialog::keyMul() { text->insert("*"); foc(); }
+void CalcDialog::keySub() { text->insert("-"); foc(); }
+void CalcDialog::keyDiv() { text->insert("/"); foc(); }
+void CalcDialog::keyBrO() { text->insert("("); foc(); }
+void CalcDialog::keyBrC() { text->insert(")"); foc(); }
+void CalcDialog::keyDot() { text->insert("."); foc(); }
void CalcDialog::clear() { text->clear(); foc(); }
//-----------------------------------------------------------------------------
void CalcDialog::keyFnc()
{
- text->setText(func->currentText());
- text->setCursorPosition(func->currentText().length()-1); foc();
+ text->insert(func->currentText());
+ text->setCursorPosition(text->cursorPosition()-1); foc();
}
//-----------------------------------------------------------------------------
void CalcDialog::keyPut() { emit putNumber(result->text()); }
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<mime-type xmlns="http://www.freedesktop.org/standards/shared-mime-info" type="text/mgl">
+ <comment>MGL script</comment>
+ <icon name="/usr/local/share/pixmaps/udav.png"/>
+ <glob pattern="*.mgl"/>
+</mime-type>
a = new QHBoxLayout; o->addLayout(a);
l = new QLabel(tr("Data name")); a->addWidget(l);
- char buf[32]; snprintf(buf,32,"mgl_%d",numDataOpened);
+ char buf[32]; snprintf(buf,32,"mgl_%d",numDataOpened); buf[31]=0;
name = new QLineEdit(buf,this); a->addWidget(name);
rA = new QRadioButton(tr("Auto detect data sizes"), this);
{
code = ""; numDataOpened++; data = name->text();
// prepare unique value of name for next time
- char buf[32]; snprintf(buf,32,"mgl_%d",numDataOpened); name->setText(buf);
+ char buf[32]; snprintf(buf,32,"mgl_%d",numDataOpened);
+ buf[31]=0; name->setText(buf);
mglData *v = parser.AddVar(data.toStdString().c_str());
int dd=0;
if(rA->isChecked()) // auto sizes
Icon=udav
Name=UDAV
Exec=udav
+MimeType=text/mgl;
Comment=Data handling and plotting tool
Comment[en_US]=Data handling and plotting tool
Comment[ru_RU]=Обработка и отображение данных
// try to fix possible multi-threading errors
// must be placed before ANY window creation
XInitThreads();
+#endif
+#ifdef WIN32
+ char buf[512]; getcwd(buf,500); strcat(buf,"\\plugins\\");
+ QCoreApplication::addLibraryPath(buf);
+ QCoreApplication::addLibraryPath("c:\\plugins\\");
#endif
mgl_ask_func = mgl_ask_qt;
QApplication a(argc, argv);
p.Execute(&gr,str.c_str());\r
if(gr.Message()[0]) printf("%s\n",gr.Message());\r
gr.EndFrame();\r
- snprintf(buf,2048,"%s-%ld",oname,i);\r
+ snprintf(buf,2048,"%s-%ld",oname,i); buf[2047]=0;\r
if(!gif) gr.WriteFrame(buf);\r
}\r
if(gif) gr.CloseGIF();\r
mglPoint p = gr->CalcXYZ(Fl::event_x()-x(), Fl::event_y()-y());
if(g) g->LastMousePos = p;
char s[128];
- snprintf(s,128,"x=%g, y=%g, z=%g",p.x,p.y,p.z);
+ snprintf(s,128,"x=%g, y=%g, z=%g",p.x,p.y,p.z); s[127]=0;
draw(); fl_color(FL_BLACK); fl_draw(s,40,70);
}
}
Adjust();
}
- char *tmp[1]; tmp[0]=new char[1]; tmp[0][0]=0;
- Wnd->show(argv ? argc:0, argv ? argv:tmp);
- delete []tmp[0];
-}
+ static char ctmp[1]; ctmp[0]=0;
+ static char *tmp[1]; tmp[0]=ctmp;
+ Wnd->show(argv ? argc:0, argv ? argv:tmp);}
//-----------------------------------------------------------------------------
HMGL MGL_EXPORT mgl_create_graph_fltk(int (*draw)(HMGL gr, void *p), const char *title, void *par, void (*load)(void *p))
{
{\r
char str[128];\r
snprintf(str,128,"%s_%d.png",_mgl_glwnd->PlotId.c_str(),_mgl_glwnd->curr_fig);\r
- mgl_write_png(_mgl_glwnd, str, "Math GL");\r
+ str[127]=0; mgl_write_png(_mgl_glwnd, str, "MathGL");\r
}\r
if(ch=='J')\r
{\r
char str[128];\r
snprintf(str,128,"%s_%d.jpg",_mgl_glwnd->PlotId.c_str(),_mgl_glwnd->curr_fig);\r
- mgl_write_jpg(_mgl_glwnd, str, "Math GL");\r
+ str[127]=0; mgl_write_jpg(_mgl_glwnd, str, "MathGL");\r
}\r
if(ch=='E')\r
{\r
char str[128];\r
snprintf(str,128,"%s_%d.eps",_mgl_glwnd->PlotId.c_str(),_mgl_glwnd->curr_fig);\r
- mgl_write_eps(_mgl_glwnd, str, "Math GL");\r
+ str[127]=0; mgl_write_eps(_mgl_glwnd, str, "MathGL");\r
}\r
if(ch=='S')\r
{\r
char str[128];\r
snprintf(str,128,"%s_%d.svg",_mgl_glwnd->PlotId.c_str(),_mgl_glwnd->curr_fig);\r
- mgl_write_svg(_mgl_glwnd, str, "Math GL");\r
+ str[127]=0; mgl_write_svg(_mgl_glwnd, str, "MathGL");\r
}\r
if(ch==' ') _mgl_glwnd->Clf();\r
if(ch=='m') _mgl_glwnd->tt = 1-_mgl_glwnd->tt;\r
//-----------------------------------------------------------------------------
void QMathGL::drawPrim()
{
-// mgl_clf_nfog(gr);
+ if(!gr) return;
mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);
mgl_get_frame(gr, g?g->GetCurFig():mgl_get_num_frame(gr)-1);
mglParse pr;
else mgl_view(gr,-phi,-tet,0);
}
}
- mglConvertFromGraph(pic, gr, &grBuf);
+ mglConvertFromGraph(pic, gr, &grBuf, &img);
if(pic.size()!=size()) setSize(pic.width(), pic.height());
repaint();
}
{
if(fname.isEmpty()) fname = mgl_get_plotid(gr);
if(fname.isEmpty()) QMessageBox::critical(this, appName, tr("No filename."),QMessageBox::Ok,0,0);
- else mgl_write_gif(gr,setExtension(fname,"png").toStdString().c_str(), appName.toStdString().c_str());
+ else
+#if MGL_HAVE_GIF
+ mgl_write_gif(gr,setExtension(fname,"png").toStdString().c_str(), appName.toStdString().c_str());
+#else
+ img.save(setExtension(fname,"gif"));
+#endif
}
//-----------------------------------------------------------------------------
void QMathGL::exportPNG(QString fname)
{
if(fname.isEmpty()) fname = mgl_get_plotid(gr);
if(fname.isEmpty()) QMessageBox::critical(this, appName, tr("No filename."),QMessageBox::Ok,0,0);
- else mgl_write_png(gr,setExtension(fname,"png").toStdString().c_str(), appName.toStdString().c_str());
+ else
+#if MGL_HAVE_PNG
+ mgl_write_png(gr,setExtension(fname,"png").toStdString().c_str(), appName.toStdString().c_str());
+#else
+ img.save(setExtension(fname,"png"));
+#endif
}
//-----------------------------------------------------------------------------
void QMathGL::exportPNGs(QString fname)
{
if(fname.isEmpty()) fname = mgl_get_plotid(gr);
if(fname.isEmpty()) QMessageBox::critical(this, appName, tr("No filename."),QMessageBox::Ok,0,0);
- else mgl_write_png_solid(gr,setExtension(fname,"png").toStdString().c_str(), appName.toStdString().c_str());
+ else
+#if MGL_HAVE_PNG
+ mgl_write_png_solid(gr,setExtension(fname,"png").toStdString().c_str(), appName.toStdString().c_str());
+#else
+ img.save(setExtension(fname,"png"));
+#endif
}
//-----------------------------------------------------------------------------
void QMathGL::exportJPG(QString fname)
{
if(fname.isEmpty()) fname = mgl_get_plotid(gr);
if(fname.isEmpty()) QMessageBox::critical(this, appName, tr("No filename."),QMessageBox::Ok,0,0);
- else mgl_write_jpg(gr,setExtension(fname,"jpg").toStdString().c_str(), appName.toStdString().c_str());
+ else
+#if MGL_HAVE_JPEG
+ mgl_write_jpg(gr,setExtension(fname,"jpg").toStdString().c_str(), appName.toStdString().c_str());
+#else
+ img.save(setExtension(fname,"jpg"));
+#endif
}
//-----------------------------------------------------------------------------
void QMathGL::exportBPS(QString fname)
}
}
//-----------------------------------------------------------------------------
-void mglConvertFromGraph(QPixmap &pic, mglCanvas *gr, uchar **buf)
+void mglConvertFromGraph(QPixmap &pic, mglCanvas *gr, uchar **buf, QImage *out)
{
const uchar *bb = mgl_get_rgb(gr);
register long i,w=mgl_get_width(gr), h=mgl_get_height(gr);
(*buf)[4*i+3] = 255;
}
QImage img(*buf, w, h, QImage::Format_RGB32);
+ if(out) *out = img;
pic = QPixmap::fromImage(img);
}
//-----------------------------------------------------------------------------