%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 \section{Setup} %D LaTeX preamble variables string latexmp_docclass, latexmp_classoptions, latexmp_inputenc, latexmp_fontenc, latexmp_babellang, latexmp_packages, latexmp_preamble, latexmp_lmpprefix, latexmp_preamblefile ; latexmp_docclass := "article" ; latexmp_classoptions := "" ; latexmp_inputenc := "" ; latexmp_fontenc := "" ; latexmp_babellang := "" ; latexmp_packages := "" ; latexmp_preamble := "" ; latexmp_preamblefile := "" ; %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 ; latexmp_color_Hsv := "Hsvcolor_latexmp" ; latexmp_color_gray := "graycolor_latexmp" ; latexmp_color_rgb := "" ; latexmp_color_cmyk := "cmykcolor_latexmp" ; latexmp_color_named := "" ; %D \section{Key-Value Support Macros} def processKeyvals_latexmp (text _kvps_)= begingroup; save _equals, _assign ; let _equals= = ; primarydef _ll_ _assign _rr_ = hide(_ll_ _equals _rr_ ) 1 enddef; save = ; let = _equals _assign ; for _xx_ _equals _kvps_ : endfor ;% NOP endgroup; enddef;