%D \module
%D [ file=latexmp.mp,
%D system={latexMP},
%D version=1.2.1,
%D title=latexMP,
%D subtitle=LaTeX typesetting in \METAPOST,
%D author=Jens-Uwe Morawski,
%D date={2005/04/06},
%D copyright={none; this module is Public Domain}]
%D
%C - all variables start with prefix "latexmp_"
%C - all internal macros have suffix "_latexmp"
%C - macros without "_latexmp" suffix are:
%C textext, setupLaTeXMP
%D \section{Initialisation}
if known latexmp_module: message(" not loaded again"); endinput ; fi ;
boolean latexmp_module ; latexmp_module := true ;
%D set the name of the temporary file
string latexmp_lmpfile ; latexmp_lmpfile := "ltx-" & jobname & ".tmp" ;
%D save some original \METAPOST\ definitions
inner end ; inner bye ;
let origEnd_latexmp=end ;
let origBye_latexmp=bye ;
let origShipit_latexmp=shipit ;
string latexmp_extrabeginfig, latexmp_extraendfig ;
extra_endfig := extra_endfig & "; resetattachstrings_latexmp ;" ;
latexmp_extrabeginfig := extra_beginfig ;
latexmp_extraendfig := extra_endfig ;
color latexmp_background ;
latexmp_background := background ;
%D The runtime control of latexMP states:
%D (1) is this the second run in \type{rerun} mode ; (2) has the temporary
%D mp file already been read; (3) is the LaTeX preamble already
%D been written to the temporary file
boolean latexmp_secondrun, latexmp_lmploaded, latexmp_texinit ;
latexmp_secondrun := false ;
latexmp_lmploaded := false ;
latexmp_texinit := false ;
%D The current number of \type{textext()} in the input file. The counter
%D is incremented at every \type{textext} call. It is used to assign the
%D pictures from the temporary file.
numeric latexmp_counter ; latexmp_counter := 0 ;
%D The setup variables that control activation of the specials:
numeric latexmp_mode ; latexmp_mode := 1 ;
boolean latexmp_subsinfont ; latexmp_subsinfont := false ;
boolean latexmp_multicolor ; latexmp_multicolor := false ;
boolean latexmp_debug ; latexmp_debug := false ;
%D The setup command:
def setupLaTeXMP(text kvps) =
if not latexmp_secondrun:
if latexmp_texinit:
message("LaTeXMP: setupLaTeXMP cannot be used if textext" &
"has already been used; set-up ignored.");
else:
begingroup;
%D declaration of key-value parameters for LaTeX preamble
save class, options, inputencoding, fontencoding, language,
packages, preamble, preamblefile ;
string class, options, inputencoding, fontencoding, language,
packages, preamble, preamblefile;
%D declaration of key and synonyms for \type{mode}
save mode, normal, rerun ;
numeric mode, normal, rerun ;
normal:=1 ; rerun := 2 ;
%D declaration of keys and synonyms for the specials
save textextlabel, multicolor, debug, enable, disable ;
boolean textextlabel, multicolor, debug, enable, disable ;
enable:=true ; disable := false ;
processKeyvals_latexmp(kvps) ;
if known class:
if (length class) >0: latexmp_docclass:=class ;
else: latex_docclass:="article";
fi;
fi;
if known options: latexmp_classoptions:=options ; fi;
if known inputencoding: latexmp_inputenc:=inputencoding ; fi;
if known fontencoding: latexmp_fontenc:=fontencoding ; fi;
if known language: latexmp_babellang:=language ; fi;
if known preamble:latexmp_preamble:=preamble ; fi;
if known preamblefile: latexmp_preamblefile:=preamblefile ; fi;
if known packages: latexmp_packages:=packages ; fi;
if known mode:
if (mode=normal) or (mode=rerun): latexmp_mode:=mode ;
else:
errmessage("latexMP error: set mode either to 'normal' or 'rerun'.") ;
latexmp_mode := 1 ;
fi;
fi;
if known textextlabel: latexmp_subsinfont:=textextlabel ; fi;
if known multicolor: latexmp_multicolor:=multicolor ; fi;
if known debug: latexmp_debug:=debug ; fi;
endgroup;
%D overwrite the default definition of \type{thelabel} if user has specified
%D \type{textextlabel=enable}:
if latexmp_subsinfont:
vardef thelabel@#(expr s,z) =
save p; picture p;
if picture s: p=s
else: p = textext(s)
fi;
p shifted (z + labeloffset*laboff@# -
(labxf@#*lrcorner p + labyf@#*ulcorner p
+ (1-labxf@#-labyf@#)*llcorner p ))
enddef;
fi;
%D In \type{rerun} mode for the first run own definitions for \type{end}
%D and \type{bye} are used; output is disabled for first run.
if latexmp_mode=2:
let end=end_latexmp ;
let bye=end_latexmp ;
let shipit=relax ;
%D Since in the first run the temporary file will not contain
%D correct definitions automatic loading of that file by \type{textext}
%D is disabled (we fake here that it is already loaded). Loading of the
%D temporary file in \type{end_latexmp}.
latexmp_lmploaded := true ;
fi;
fi;fi;
enddef;
%D used in \type{writeLaTeXpreamble_latexmp}
%D to generate \type{\usepackage} statements
def writepackages_latexmp=
begingroup;
save inoptions, currentpackage, currentoptions, s ;
boolean inoptions ; inoptions:=false;
string currentpackage, currentoptions, s ;
currentpackage:=""; currentoptions:="" ;
for c=0 upto ((length latexmp_packages)-1):
s := substring (c,c+1) of latexmp_packages ;
if s="[": inoptions := true ;
elseif s="]": inoptions := false;
elseif s=",":
if inoptions: currentoptions:= currentoptions & s ;
else:
if (length currentpackage)>0:
s:="{" & currentpackage & "}" ;
if (length currentoptions)>0:
s:="[" & currentoptions & "]" & s ;
fi;
write ("\usepackage" & s) to latexmp_lmpfile ;
currentpackage:=""; currentoptions:="" ;
fi;
fi;
else:
if inoptions: currentoptions:= currentoptions & s ;
else: currentpackage:= currentpackage & s ;
fi;
fi;
endfor;
if (length currentpackage)>0: s:="{" & currentpackage & "}" ;
if (length currentoptions)>0: s:="[" & currentoptions & "]" & s ; fi;
write ("\usepackage" & s) to latexmp_lmpfile ;
fi;
endgroup;
enddef;
%D \section{LaTeX preamble}
def writeLaTeXpreamble_latexmp =
write "verbatimtex" to latexmp_lmpfile ;
write "%&latex" to latexmp_lmpfile ;
%D If preamble file has been specified in the setup only a
%D \type{\input} for this file will be used in the LaTeX preamble:
if (length latexmp_preamblefile)>0:
write ("\input{" & latexmp_preamblefile & "}") to latexmp_lmpfile ;
else:
%D Specific definitions from the setup parameters:
write ("\documentclass"
if (length latexmp_classoptions)>0:
& "[" & latexmp_classoptions & "]"
fi & "{" & latexmp_docclass & "}") to latexmp_lmpfile ;
if (length latexmp_fontenc)>0:
write ("\usepackage[" & latexmp_fontenc & "]{fontenc}")
to latexmp_lmpfile ;
fi
if (length latexmp_inputenc)>0:
write ("\usepackage[" & latexmp_inputenc & "]{inputenc}")
to latexmp_lmpfile ;
fi
if (length latexmp_babellang)>0:
write ("\usepackage[" & latexmp_babellang & "]{babel}")
to latexmp_lmpfile ;
fi
if (length latexmp_packages)>0: writepackages_latexmp ; fi;
if (length latexmp_preamble)>0:
write latexmp_preamble to latexmp_lmpfile ;
fi
fi;
if latexmp_multicolor:
write ("\makeatletter") to latexmp_lmpfile ;
write ("\font\latexmp@special=cmtt8 scaled 250") to latexmp_lmpfile ;
write ("\def\reset@color{" &
"\parbox[t][0pt][t]{0pt}{\makebox[0pt][l]{\latexmp@special ecolorxxx}}}")
to latexmp_lmpfile ;
write ("\newcommand*{\color}[2][named]{\parbox[t][0pt][t]{0pt}{" &
"\makebox[0pt][l]{\latexmp@special bcolorxxx:#1:#2}}" &
"\aftergroup\reset@color\ignorespaces}") to latexmp_lmpfile ;
write ("\def\textcolor#1#{\@textcolor{#1}}") to latexmp_lmpfile ;
write ("\def\@textcolor#1#2#3{\protect\leavevmode{\color#1{#2}#3}}")
to latexmp_lmpfile ;
write ("\newcommand*{\transparent}[3][1]{\parbox[t][0pt][t]{0pt}{"&
"\makebox[0pt][l]{\latexmp@special btransxxx:#1,#2}}"&
"#3\parbox[t][0pt][t]{0pt}{" &
"\makebox[0pt][l]{\latexmp@special etransxxx}}}") to latexmp_lmpfile ;
write "\makeatother" to latexmp_lmpfile ;
fi;
write "\begin{document}" to latexmp_lmpfile ;
write "etex" to latexmp_lmpfile ;
write "picture latexmp_picture[];" to latexmp_lmpfile ;
enddef;
%D \section{Main Macros}
%D The macro that does the job:
vardef textext@#(expr s)=
save pic ; picture pic ;
latexmp_counter:= latexmp_counter+1 ;
getpicture_latexmp ;
addstring_latexmp(s) ;
if (length (str @#))>0 :
% V. 1.1 compatible with MetaFun
thelabel@#(pic,origin)
else:
% V. 1.2 better compatibility with btex..etex
pic
fi
enddef;
%D strings \type{latexmp_prepend} and \type{latexmp_append} are attached
%D to the string passed to \type{textext}. This may be useful for package
%D authors to implement styling interfaces.
string latexmp_prepend, latexmp_append ;
latexmp_prepend:= "" ; latexmp_append := "" ;
%D is called at each endfig via extra_endfig
def resetattachstrings_latexmp =
latexmp_prepend:= "" ; latexmp_append := "" ;
enddef;
def addstring_latexmp(expr s)=
if not latexmp_texinit:
write EOF to latexmp_lmpfile ;
writeLaTeXpreamble_latexmp ;
latexmp_texinit := true ;
fi;
write "latexmp_picture[" & (decimal latexmp_counter) & "]:= btex " &
latexmp_prepend & s & latexmp_append & " etex ;" to latexmp_lmpfile ;
enddef;
def getpicture_latexmp =
if not latexmp_lmploaded:
if not (readfrom latexmp_lmpfile=EOF):
scantokens ("input " & latexmp_lmpfile) ;
fi;
latexmp_lmploaded := true ;
fi;
if known latexmp_picture[latexmp_counter]:
if latexmp_multicolor and not latexmp_debug:
pic := colorspecials_latexmp(latexmp_picture[latexmp_counter]) ;
else:
pic := latexmp_picture[latexmp_counter] ;
fi;
else:
pic := ("LaTeXMP " & (decimal latexmp_counter))
infont defaultfont ;
fi;
enddef;
%D The following is only used if option \type{multicolor} is set in
%D \type{setupLaTeXMP}. It is employed in \type{getpicture_latexmp}
%D in order to strip specials from the LaTeX picture and change
%D the colors of text elements accordigly.
vardef colorspecials_latexmp(expr p) =
save _P, _bb, _tp, _fp, _t, _addto_P ;
save _withcolor, _colorpointer, _transparent, _transpointer;
picture _P ; path _bb ;
string _withcolor[], _transparent[], _tp, _fp, _addto_P ;
numeric _colorpointer, _transpointer ;
_P := nullpicture ; _bb := pathpart p ;
_withcolor[0]:= "" ; _colorpointer := 0 ; _transparent[0]:="" ;
_transpointer:=0 ;
_addto_P := "addto _P also _tp infont _fp transformed _t " ;
for c within p:
if textual c:
_tp:= textpart c ;
_fp:= fontpart c ;
transform _t ;
(xpart _t,xxpart _t,xypart _t)=(xpart c,xxpart c,xypart c) ;
(ypart _t,yypart _t,yxpart _t)=(ypart c,yypart c,yxpart c) ;
if (_fp="cmtt8") and ((substring (1,9) of _tp)="colorxxx"):
% color special found
if (substring (0,1) of _tp)="b":
% begin color special
_colorpointer := _colorpointer+1;
_withcolor[_colorpointer]:= colormacro_latexmp(substring (10,(length _tp)) of _tp) ;
elseif (substring (0,1) of _tp)="e":
% end color special
if not (_colorpointer=0):
%C if \type{\color} is used ungrouped in a parbox the \type{ecolorxxx}
%C appears prior \type{bcolorxxx}. multiple instances of \type{ecolorxxx}
%C would result in counting \type{_colorpointer<0}. thus checking
%C for \type{_colorpointer=0} is a ugly hack for this problem.
_colorpointer := _colorpointer-1;
fi;
%C else:?? ooops; should not happen
fi;
elseif (_fp="cmtt8") and ((substring (1,9) of _tp)="transxxx"):
% transparency special found
if (substring (0,1) of _tp)="b":
% begin trans special
_transpointer := _transpointer+1;
_transparent[_transpointer]:= substring (10,(length _tp)) of _tp ;
elseif (substring (0,1) of _tp)="e":
% end trans special
_transpointer := _transpointer-1;
fi;
else:
scantokens (_addto_P & withcurrentcolor_latexmp ) ;
fi;
fi;
endfor;
setbounds _P to _bb ;
_P
enddef;
vardef colormacro_latexmp(expr colspec)=
save _cmd, _pos, _m, _c ; string _cmd, _m, _c ;
_pos := 0 ; _cmd:="" ;
for i=1 upto (length colspec):
if (substring (i-1,i) of colspec)=":":
_pos := i ;
fi;
endfor;
if _pos<2: % "x:..." --> no color model found
errmessage("LaTeXMP: no color model found in: " & colspec) ;
else:
_m := substring (0,(_pos-1)) of colspec ;
_c := substring (_pos,(length colspec)) of colspec ;
if expandafter known (scantokens ("latexmp_color_" & _m)):
_cmd := (scantokens ("latexmp_color_" & _m)) & "(" & _c & ")" ;
else:
errmessage("LaTeXMP: color model '" & _m & "' not supported)") ;
fi;
fi;
_cmd
enddef;
vardef withcurrentcolor_latexmp=
if (length _withcolor[_colorpointer])>0:
if (length _transparent[_transpointer])>0:
" withcolor transparent(" & _transparent[_transpointer] & "," &
_withcolor[_colorpointer] &")"
else: " withcolor " & _withcolor[_colorpointer] fi
else:
if (length _transparent[_transpointer])>0:
" withcolor transparent(" & _transparent[_transpointer] & ",black)"
else: "" fi
fi
enddef;
%D \section{The end macro for rerun mode}
string latexmp_beforererun ; latexmp_beforererun := "" ;
def end_latexmp =
%D read temporary file if strings have been written there
if latexmp_counter>0:
write EOF to latexmp_lmpfile;
scantokens ("input " & latexmp_lmpfile) ;
fi;
%D re-init
latexmp_counter := 0 ; latexmp_secondrun := true ; latexmp_texinit := false ;
%D restore defaults
extra_beginfig := latexmp_extrabeginfig ;
extra_endfig := latexmp_extraendfig ;
background := latexmp_background ;
let end=origEnd_latexmp ; let bye=origBye_latexmp ;
let shipit=origShipit_latexmp ;
clear_pen_memory; clearit;
pickup pencircle scaled .5bp; defaultpen := savepen;
%D run pre-rerun hooks
scantokens latexmp_beforererun ;
%D input current job again
scantokens ("input " & jobname) ;
enddef;
%D \section{color support}
vardef Hsvcolor_latexmp(expr H,s,v) =
save h, o, b, d, pc, sc; numeric h, o, b, d, pc, sc ;
h := H/60 ; pc := floor h ; sc := h - pc ;
o := (1-s)*v ; b := (1-(sc*s))*v ; d := (1-((1-sc)*s))*v ;
if (pc = 0) or (pc = 6): (v,d,o)
elseif pc = 1: (b,v,o)
elseif pc = 2: (o,v,d)
elseif pc = 3: (o,b,v)
elseif pc = 4: (d,o,v)
else:(v,o,b)
fi
enddef;
vardef cmykcolor_latexmp(expr c,m,y,k) =
%D use MetaFun cmyk-specials if available; macro \type{cmyk()}
%D checks if \type{cmykcolors=true}
if known context_spec: cmyk(c,m,y,k) else: (1-c-k,1-m-k,1-y-k) fi
enddef;
vardef graycolor_latexmp(expr g) = (g,g,g) enddef ;
%D which macro should be used for a given color model in multicolor mode.
string latexmp_color_Hsv, latexmp_color_rgb,
latexmp_color_gray, latexmp_color_cmyk, latexmp_color_named ;