diff options
51 files changed, 3843 insertions, 275 deletions
diff --git a/context/data/context.properties b/context/data/context.properties index 4c15b6666..ef21dc907 100644 --- a/context/data/context.properties +++ b/context/data/context.properties @@ -406,7 +406,8 @@ tabbar.multiline=1 # Editor: handy anyway line.margin.visible=1 -line.numbers=6 +#~ line.numbers=6 +line.margin.width=3+ title.full.path=1 strip.trailing.spaces=1 save.session=1 diff --git a/scripts/context/ruby/base/tex.rb b/scripts/context/ruby/base/tex.rb index 61d857d19..16544c420 100644 --- a/scripts/context/ruby/base/tex.rb +++ b/scripts/context/ruby/base/tex.rb @@ -139,10 +139,11 @@ class TEX ['cont-en','cont-nl','cont-de','cont-it', 'cont-fr','cont-cz','cont-ro','cont-uk'] .each do |f| @@texprocstr[f] = "\\emergencyend" end - # @@runoptions['xetex'] = ['--output-driver \\\"-d 4 -V 5\\\"'] # we need the pos pass - @@runoptions['xetex'] = ['--no-pdf'] # from now on we assume (x)dvipdfmx to be used - - # @@runoptions['luatex'] = ['--progname=pdftex'] + # @@runoptions['xetex'] = ['--output-driver \\\"-d 4 -V 5\\\"'] # we need the pos pass + @@runoptions['xetex'] = ['--8bit --no-pdf'] # from now on we assume (x)dvipdfmx to be used + @@runoptions['pdfetex'] = ['--8bit'] + @@runoptions['luatex'] = ['--8bit'] + @@runoptions['aleph'] = ['--8bit'] @@booleanvars = [ 'batchmode', 'nonstopmode', 'fast', 'fastdisabled', 'silentmode', 'final', diff --git a/scripts/context/ruby/base/texutil.rb b/scripts/context/ruby/base/texutil.rb index 89f5e5385..7b3e957e3 100644 --- a/scripts/context/ruby/base/texutil.rb +++ b/scripts/context/ruby/base/texutil.rb @@ -230,7 +230,8 @@ class TeXUtil end def normalize(str) - replace(str).gsub(/ +/,' ') + # replace(str).gsub(/ +/,' ') + replace(str).gsub(/\s\s+/," \\space") end def tokenize(str) @@ -267,16 +268,16 @@ class TeXUtil s end - def preset(shortcuts=[],expansions=[],reductions=[],divisions=[]) + def preset(shortcuts=[],expansions=[],reductions=[],divisions=[],language='') 'a'.upto('z') do |c| expander(c) ; division(c) end 'A'.upto('Z') do |c| expander(c) ; division(c) end expander('1','b') ; expander('2','c') ; expander('3','e') ; expander('4','f') expander('5','g') ; expander('6','h') ; expander('7','i') ; expander('8','i') expander('9','j') ; expander('0','a') ; expander('-','-') ; - shortcuts.each do |s| shortcut(s[0],s[1]) end - expansions.each do |e| expander(e[0],e[1]) end - reductions.each do |r| reducer(r[0],r[1]) end - divisions.each do |d| division(d[0],d[1]) end + shortcuts.each do |s| shortcut(s[1],s[2]) if s[0] == '' || s[0] == language end + expansions.each do |e| expander(e[1],e[2]) if e[0] == '' || e[0] == language end + reductions.each do |r| reducer(r[1],r[2]) if r[0] == '' || r[0] == language end + divisions.each do |d| division(d[1],d[2]) if d[0] == '' || d[0] == language end end def simplify(str) @@ -490,16 +491,23 @@ class TeXUtil end - @@synonyms = Hash.new + @@synonyms = Hash.new + @@sorter = Hash.new + @@languages = Hash.new def MySynonyms::reset(logger) - @@synonyms = Hash.new + @@synonyms = Hash.new + @@sorter = Hash.new + @@languages = Hash.new end def MySynonyms::reader(logger,data) - if data[0] == 'e' then - @@synonyms[data[1]] = Array.new unless @@synonyms.key?(data[1]) - @@synonyms[data[1]].push(Synonym.new(data[1],data[2],data[3],data[4])) + case data[0] + when 'e' then + @@synonyms[data[1]] = Array.new unless @@synonyms.key?(data[1]) + @@synonyms[data[1]].push(Synonym.new(data[1],data[2],data[3],data[4])) + when 'l' then + @@languages[data[1]] = data[2] || '' end end @@ -513,12 +521,17 @@ class TeXUtil end def MySynonyms::processor(logger) - sorter = Sorter.new - sorter.preset(eval("MyKeys").shortcuts,eval("MyKeys").expansions,eval("MyKeys").reductions,eval("MyKeys").divisions) - sorter.prepare @@synonyms.keys.each do |s| + @@sorter[s] = Sorter.new + @@sorter[s].preset( + eval("MyKeys").shortcuts, + eval("MyKeys").expansions, + eval("MyKeys").reductions, + eval("MyKeys").divisions, + @@languages[s] || '') + @@sorter[s].prepare @@synonyms[s].each_index do |i| - @@synonyms[s][i].build(sorter) + @@synonyms[s][i].build(@@sorter[s]) end @@synonyms[s] = @@synonyms[s].sort end @@ -550,6 +563,7 @@ class TeXUtil @key = @entry.dup if @key.empty? @sortkey = @key.dup @nofentries, @nofpages = 0, 0 + @normalizeentry = false end attr_reader :state, :type, :location, :key, :entry, :seetoo, :page, :realpage, :texthowto, :pagehowto @@ -557,7 +571,9 @@ class TeXUtil attr_writer :sortkey def build(sorter) - @entry, @key = sorter.normalize(@entry), sorter.normalize(sorter.tokenize(@key)) + # @entry, @key = sorter.normalize(@entry), sorter.normalize(sorter.tokenize(@key)) + @entry = sorter.normalize(sorter.tokenize(@entry)) if @normalizeentry + @key = sorter.normalize(sorter.tokenize(@key)) if false then @entry, @key = [@entry, @key].collect do |target| # +a+b+c &a&b&c a+b+c a&b&c @@ -738,11 +754,13 @@ end end @@registers = Hash.new - @@sorter = Sorter.new + @@sorter = Hash.new + @@languages = Hash.new def MyRegisters::reset(logger) @@registers = Hash.new - @@sorter = Sorter.new + @@sorter = Hash.new + @@languages = Hash.new end def MyRegisters::reader(logger,data) @@ -759,6 +777,8 @@ end when 's' then @@registers[data[1]] = Array.new unless @@registers.key?(data[1]) @@registers[data[1]].push(Register.new(4,data[1],data[2],data[3],data[4],data[5],data[6],nil)) + when 'l' then + @@languages[data[1]] = data[2] || '' end end @@ -766,18 +786,24 @@ end if @@registers.size > 0 then @@registers.keys.sort.each do |s| handle << logger.banner("registers: #{s} #{@@registers[s].size}") - Register.flush(@@registers[s],handle,@@sorter) + Register.flush(@@registers[s],handle,@@sorter[s]) # report("register #{@@registers[s].class}: #{@@registers[s].@nofentries} entries and #{@@registers[s].@nofpages} pages") end end end def MyRegisters::processor(logger) - @@sorter.preset(eval("MyKeys").shortcuts,eval("MyKeys").expansions,eval("MyKeys").reductions,eval("MyKeys").divisions) - @@sorter.prepare @@registers.keys.each do |s| + @@sorter[s] = Sorter.new + @@sorter[s].preset( + eval("MyKeys").shortcuts, + eval("MyKeys").expansions, + eval("MyKeys").reductions, + eval("MyKeys").divisions, + @@languages[s] || '') + @@sorter[s].prepare @@registers[s].each_index do |i| - @@registers[s][i].build(@@sorter) + @@registers[s][i].build(@@sorter[s]) end @@registers[s] = @@registers[s].sort end @@ -861,7 +887,7 @@ end def MyKeys::reader(logger,data) key = data.shift - grp = data.shift # language code, todo + # grp = data.shift # language code, todo case key when 's' then @@shortcuts.push(data) when 'e' then @@expansions.push(data) diff --git a/scripts/context/ruby/ctxtools.rb b/scripts/context/ruby/ctxtools.rb index 69c6885b4..5686468f1 100644 --- a/scripts/context/ruby/ctxtools.rb +++ b/scripts/context/ruby/ctxtools.rb @@ -529,6 +529,7 @@ class Commands "tui", "tup", "ted", "tes", "top", "log", "tmp", "run", "bck", "rlg", "mpt", "mpx", "mpd", "mpo", "ctl", + "tmp.md5", "tmp.out" ] $texonlysuffixes = [ "dvi", "ps", "pdf" diff --git a/scripts/context/ruby/texexec.rb b/scripts/context/ruby/texexec.rb index b74b6c793..3dab3e9ce 100644 --- a/scripts/context/ruby/texexec.rb +++ b/scripts/context/ruby/texexec.rb @@ -137,7 +137,8 @@ class Commands files = @commandline.arguments.sort if files.length > 0 then if f = File.open(job.tempfilename('tex'),'w') then - job.runtexutil(files,"--figures", true) + # will be replaced + Kpse.runscript('texutil',files.join(' '),'--figures') figures = @commandline.checkedoption('method', 'a').downcase paperoffset = @commandline.checkedoption('paperoffset', '0pt') backspace = @commandline.checkedoption('backspace', '1.5cm') @@ -194,8 +195,7 @@ class Commands fnames.each do |ffname| if msuffixes.include?(File.splitname(ffname)[1]) && FileTest.file?(ffname) then if mod = File.open(job.tempfilename('tex'),'w') then - # will become a call to ctxtools - job.runtexutil(ffname,"--documents", true) + Kpse.runscript('ctxtools',ffname,'--document') if ted = File.silentopen(File.suffixed(ffname,'ted')) then firstline = ted.gets if firstline =~ /interface=/o then diff --git a/scripts/context/ruby/texmfstart.rb b/scripts/context/ruby/texmfstart.rb index e1d688f67..66bab6261 100644 --- a/scripts/context/ruby/texmfstart.rb +++ b/scripts/context/ruby/texmfstart.rb @@ -23,6 +23,7 @@ # --locate => provides location # --exec => exec instead of system # --iftouched=a,b => only if timestamp a<>b +# --ifchanged=a,b => only if checksum changed # # file: path: bin: @@ -35,6 +36,7 @@ $ownpath = File.expand_path(File.dirname($0)) unless defined? $ownpath $: << $ownpath require "rbconfig" +require "md5" # kpse_merge_done: require 'base/kpseremote' # kpse_merge_done: require 'base/kpsedirect' @@ -1494,6 +1496,7 @@ $makelist = [ 'tmftools', 'exatools', 'runtools', + 'rlxtools', # # no, 'texmfstart' ] @@ -2107,7 +2110,7 @@ end def run(fullname) if ! fullname || fullname.empty? then - report("the file '#{$filename}' is not found") + output("the file '#{$filename}' is not found") elsif FileTest.file?(fullname) then begin case fullname @@ -2222,6 +2225,35 @@ def process(&block) else report("file #{oldname} is untouched") end + elsif $ifchanged then + filename = $directives['ifchanged'] + checkname = filename + ".md5" + oldchecksum, newchecksum = "old", "new" + begin + newchecksum = MD5.new(IO.read(filename)).hexdigest.upcase + rescue + newchecksum = "new" + else + begin + oldchecksum = IO.read(checkname).chomp + rescue + oldchecksum = "old" + end + end + if oldchecksum != newchecksum then + report("old checksum #{filename}: #{oldchecksum}") + report("new checksum #{filename}: #{newchecksum}") + report("file is changed, processing started") + begin + File.open(checkname,'w') do |f| + f << newchecksum + end + rescue + end + yield + else + report("file #{filename} is unchanged") + end else yield end @@ -2370,6 +2402,7 @@ def execute(arguments) $after = $directives['after'] || '' $iftouched = $directives['iftouched'] || false + $ifchanged = $directives['ifchanged'] || false $openoffice = $directives['oo'] || false diff --git a/scripts/context/ruby/textools.rb b/scripts/context/ruby/textools.rb index 3c257b7db..993388347 100644 --- a/scripts/context/ruby/textools.rb +++ b/scripts/context/ruby/textools.rb @@ -98,7 +98,6 @@ class Commands end end - end class Commands diff --git a/scripts/context/stubs/mswin/rlxtools.bat b/scripts/context/stubs/mswin/rlxtools.bat new file mode 100755 index 000000000..b78dec13b --- /dev/null +++ b/scripts/context/stubs/mswin/rlxtools.bat @@ -0,0 +1,2 @@ +@echo off +texmfstart rlxtools.rb %* diff --git a/scripts/context/stubs/unix/rlxtools b/scripts/context/stubs/unix/rlxtools new file mode 100755 index 000000000..6cd5db89f --- /dev/null +++ b/scripts/context/stubs/unix/rlxtools @@ -0,0 +1,2 @@ +#!/bin/sh +texmfstart rlxtools.rb $@ diff --git a/tex/context/base/colo-ini.tex b/tex/context/base/colo-ini.tex index 0fac60740..007629620 100644 --- a/tex/context/base/colo-ini.tex +++ b/tex/context/base/colo-ini.tex @@ -144,7 +144,7 @@ 8: specifica -- del colore -- convertita in nero 9: spazio dei colori -- non supportato 10: spazio dei colori -- supportato - 11: il colore è convertito in grigio + 11: il colore ø convertito in grigio 12: -- is registered \stopmessages @@ -158,9 +158,9 @@ 6: palett -- er tilgjengelig 7: palett -- er ikke tilgjengelig 8: spesifikasjon -- for farge -- gir kun svart - 9: -- fargerom er ikke støttet - 10: -- fargerom er støttet - 11: fargen vil bli vist som grå + 9: -- fargerom er ikke støttet + 10: -- fargerom er støttet + 11: fargen vil bli vist som grø 12: -- is registered \stopmessages diff --git a/tex/context/base/cont-new.tex b/tex/context/base/cont-new.tex index 8cd1c6975..93b9257d4 100644 --- a/tex/context/base/cont-new.tex +++ b/tex/context/base/cont-new.tex @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2006.05.28 13:28} +\newcontextversion{2006.06.07 23:34} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new @@ -91,6 +91,9 @@ \defineXMLsavecontent[rl:height]{\!!zeropoint} \stopXMLmapping +\let\rliwidth \!!zeropoint +\let\rliheight\!!zeropoint + \def\getRLIfiguredimensions#1% {\let\rliwidth \!!zeropoint \let\rliheight\!!zeropoint @@ -111,9 +114,9 @@ \edef\rliwidth {\XMLflush{rl:width}}% \edef\rliheight{\XMLflush{rl:height}}% \stopXMLignore - \stopXMLmapping} - {}% - \stopnointerference} + \stopXMLmapping + \stopnointerference} + {}} \def\getfiguredimensionsC {\ifcase\figurestatus\ifcase\figurefilemode\else diff --git a/tex/context/base/context.tex b/tex/context/base/context.tex index abc023fc3..e9cd937bd 100644 --- a/tex/context/base/context.tex +++ b/tex/context/base/context.tex @@ -31,7 +31,7 @@ %D 2004.8.30 the low level interface is english. Watch out and adapt %D your styles an modules. -\def\contextversion{2006.05.28 13:28} +\def\contextversion{2006.06.07 23:34} %D For those who want to use this: @@ -127,10 +127,10 @@ \input supp-vis.tex \input supp-fun.tex \input supp-eps.tex -\input supp-pdf.tex +%input supp-pdf.tex \input supp-spe.tex \input supp-mps.tex -\input supp-mpe.tex +%input supp-mpe.tex \input supp-tpi.tex \input supp-mat.tex \input supp-ran.tex @@ -192,6 +192,8 @@ \input unic-ini.tex %input unic-ext.tex % obsolete +% \readfile{lang-url.pat}{}{} % test + \input colo-ini.tex \input colo-ext.tex @@ -292,6 +294,7 @@ %D support is also organized in its own class of modules. \input meta-ini.tex +\input meta-pdf.tex \input meta-pag.tex \input meta-fig.tex @@ -471,15 +474,15 @@ \startinterface italian -\writestring{Questo pacchetto è basato sul Plain TeX. Usa una versione adattata del} +\writestring{Questo pacchetto è basato sul Plain TeX. Usa una versione adattata del} \writestring{meccanismo di marcatura esteso di J. Fox (1987) ad alcune parti del} \writestring{meccanismo per gli oggetti mobili laterali di D. Comenetz (1993).} -\writestring{La maggior parte del Plain TeX (\fmtversion) di D.E. Knuth è disponibile} -\writestring{e può essere usata senza problemi. Questo pacchetto usa TaBlE,} +\writestring{La maggior parte del Plain TeX (\fmtversion) di D.E. Knuth è disponibile} +\writestring{e può essere usata senza problemi. Questo pacchetto usa TaBlE,} \writestring{un pacchetto progettato da e con diritti di copia di M.J. Wichura (1988).} \writestring{Vengono generati pochi file ausiliari, alcuni dei quali devono essere} \writestring{elaborati da TeXUtil (\utilityversion). La versione attuale del blocco} -\writestring{è \blockversion.} +\writestring{è \blockversion.} \writestring{} \writestring{L'INTERFACCIA UTENTE ITALIANA E' ANCORA IN VIA DI SVILUPPO!} \writestring{THE ITALIAN USER INTERFACE IS STILL UNDER DEVELOPMENT!} diff --git a/tex/context/base/core-buf.tex b/tex/context/base/core-buf.tex index 6ee575daa..22cc62626 100644 --- a/tex/context/base/core-buf.tex +++ b/tex/context/base/core-buf.tex @@ -97,10 +97,10 @@ \startmessages norwegian library: textblocks title: tekstblokker - 1: ny versjon, andre gjennomkjøring nødvendig + 1: ny versjon, andre gjennomkjøring nødvendig 2: skriver blokker til -- 3: leser blokker fra -- - 4: andre gjennomkjøring nødvendig + 4: andre gjennomkjøring nødvendig 5: -- ikke skjult 6: -- skjult og behandlet 7: -- skjult diff --git a/tex/context/base/core-fig.tex b/tex/context/base/core-fig.tex index 0c2d4f0c3..ffec292a9 100644 --- a/tex/context/base/core-fig.tex +++ b/tex/context/base/core-fig.tex @@ -101,7 +101,7 @@ \startmessages italian library: figures title: figure 1: figura -- non trovata - 2: la figura -- non è preimpostata + 2: la figura -- non è preimpostata 3: dimensioni della figura -- prese da -- 4: dimensioni di -- caricate dal file di immagini stesso 5: dimensioni di -- caricate dal file di immagini -- diff --git a/tex/context/base/core-fil.tex b/tex/context/base/core-fil.tex index d31b4af22..157631194 100644 --- a/tex/context/base/core-fil.tex +++ b/tex/context/base/core-fil.tex @@ -41,7 +41,7 @@ \startmessages italian library: files title: file - 1: sinonimo file -- già in uso per -- + 1: sinonimo file -- già in uso per -- \stopmessages \startmessages norwegian library: files diff --git a/tex/context/base/core-itm.tex b/tex/context/base/core-itm.tex index 8d45cfa8c..d495011f1 100644 --- a/tex/context/base/core-itm.tex +++ b/tex/context/base/core-itm.tex @@ -33,11 +33,11 @@ \stopmessages \startmessages italian library: layouts - 9: attualmente non più di -- livelli di elencazione + 9: attualmente non più di -- livelli di elencazione \stopmessages \startmessages norwegian library: layouts - 9: for øyeblikket maksimalt -- nivåer i opplisting + 9: for øyeblikket maksimalt -- nivÃ¥er i opplisting \stopmessages \startmessages romanian library: layouts diff --git a/tex/context/base/core-mat.tex b/tex/context/base/core-mat.tex index 298803bd0..b80c9cc09 100644 --- a/tex/context/base/core-mat.tex +++ b/tex/context/base/core-mat.tex @@ -17,6 +17,32 @@ \unprotect +% \definemessageconstant{math} + +% \startmessages all library: math +% title: math +% 1: don't use -- here (line \the\inputlineno) +% \stopmessages + +% \def\invalidmathcommand#1{\showmessage\m!math1{#1}} + +% \let\normaleqno \eqno +% \let\normalleqno\leqno + +% \appendtoks +% \def\eqno {\invalidmathcommand{\string\eqno }}% +% \def\leqno{\invalidmathcommand{\string\leqno}}% +% \to \everydisplay + +% \appendtoks +% \let\eqno\normaleqno +% \let\leqno\normaleqno +% \to \everymath + +% \placeformula\startformula +% H(K|M,C) = H(K|C) - H(M|C)\eqno{\hbox{(\in{}[eq:keyapp])}} +% \stopformula + \def\mathortext {\ifmmode \expandafter\firstoftwoarguments diff --git a/tex/context/base/core-not.tex b/tex/context/base/core-not.tex index d4c2a5dcf..dbbc0cc0c 100644 --- a/tex/context/base/core-not.tex +++ b/tex/context/base/core-not.tex @@ -985,10 +985,10 @@ \vbox{\flushshapebox}}}% \localframed [\??vn\currentnote] - [\c!width=\v!fit, - \c!height=\v!fit, - \c!strut=\v!no, - \c!offset=\v!overlay] + [ \c!width=\v!fit, + \c!height=\v!fit, + \c!strut=\v!no, + \c!offset=\v!overlay] {\ifdim\dp0=\zeropoint % this hack is needed because \vadjust \hbox{\lower\strutdp\box0}% % in margin number placement \else % hides the (always) present depth diff --git a/tex/context/base/core-num.tex b/tex/context/base/core-num.tex index 1f89b06cb..2747ea5e7 100644 --- a/tex/context/base/core-num.tex +++ b/tex/context/base/core-num.tex @@ -72,6 +72,7 @@ \c!location=, % no longer used here, will go away (was ooit \c!zetwijze) \c!conversion=\v!numbers, \c!start=0, + \c!state=\v!start, #2]% \makecounter{\@@thenumber{#1}}% \setxvalue{\@@thenumber{#1}\c!n}{\countervalue{\@@thenumber{#1}}}% @@ -109,13 +110,22 @@ % {\pluscounter{\@@thenumber{#1}}} % {\setcounter{\@@thenumber{#1}}{0\csname\@@thenumber{#1}\c!start\endcsname}}} +% \def\incrementnumber[#1]% bypage tricky: needs a +% {\doifelse{\numberparameter{#1}\c!way}{\v!by\v!page} +% {\checkpagechange{#1}% +% \ifpagechanged\resetcounter{\@@thenumber{#1}}\fi} +% {\checknumber[#1]}% +% \doifelse\@@nrstate\v!start % only here +% {\pluscounter{\@@thenumber{#1}}} +% {\setcounter{\@@thenumber{#1}}{0\numberparameter{#1}\c!start}}} + \def\incrementnumber[#1]% bypage tricky: needs a {\doifelse{\numberparameter{#1}\c!way}{\v!by\v!page} {\checkpagechange{#1}% \ifpagechanged\resetcounter{\@@thenumber{#1}}\fi} {\checknumber[#1]}% \doifelse\@@nrstate\v!start % only here - {\pluscounter{\@@thenumber{#1}}} + {\doif{\numberparameter{#1}\c!state}\v!start{\pluscounter{\@@thenumber{#1}}}} {\setcounter{\@@thenumber{#1}}{0\numberparameter{#1}\c!start}}} % \defineenumeration [test] [way=bypage,text=\lastchangedpage] diff --git a/tex/context/base/core-ref.tex b/tex/context/base/core-ref.tex index 4d31bf3a0..f3224d94d 100644 --- a/tex/context/base/core-ref.tex +++ b/tex/context/base/core-ref.tex @@ -93,14 +93,14 @@ 3: riferimento di tipo sconosciuto -- 4: riferimento illecito -- 21: documento -- caricato - 22: il documento -- non è interattivo + 22: il documento -- non ø interattivo 23: riferimento ambiguo -- (prefisso=--) \stopmessages \startmessages norwegian library: references title: referanser 1: ukjent referanse -- - 2: duplikat referanse -- på side -- + 2: duplikat referanse -- pø side -- 3: ukjent referansetype -- 4: ulovlig referanse -- 21: dokument -- er lest inn diff --git a/tex/context/base/core-reg.tex b/tex/context/base/core-reg.tex index 44c616107..a192c6526 100644 --- a/tex/context/base/core-reg.tex +++ b/tex/context/base/core-reg.tex @@ -80,6 +80,34 @@ % % \index[Ätsch]{Ätsch} test \index{QÄtsch} test \index[ratsch]{RÄtsch} test +% \def\doprocesspageregister[#1]#2#3% key altnum entry +% {\begingroup +% \thisisnextinternal\s!ind +% \ifduplicate\getlastregisterentry{#3}\fi +% \convertexpanded{\registerparameter\c!keyexpansion}{#1}\asciiregisterentryA +% \convertexpanded{\registerparameter\c!expansion }{#3}\asciiregisterentryB +% \doifsomething{\registerparameter\c!keyexpansion} +% {\ifx\asciiregisterentryA\empty +% \convertexpanded{\registerparameter\c!keyexpansion}{#3}\asciiregisterentryA +% \fi}% +% \makesectionformat +% \doifelse{\registerparameter\c!ownnumber}\v!yes +% \donetrue\donefalse +% % the spaces between } { are essential for texutil's split +% \expanded +% {\writeutility% +% {r \ifcase\registerpagestatus\space\or e \or f \or t \fi +% {\currentregister} % +% {\nextinternalreference} % +% {\asciiregisterentryA} % +% {\asciiregisterentryB} % +% {\sectionformat\sectionseparator\sectionseparator +% \ifdone#2\else\noexpand\pagenumber\fi} % +% {\noexpand\realfolio}}}% +% \getfirstcharacter\currentregister +% \registerinfo{> \firstcharacter}{#3}% +% \endgroup} + \def\doprocesspageregister[#1]#2#3% key altnum entry {\begingroup \thisisnextinternal\s!ind @@ -432,9 +460,13 @@ %D Don't use \type{\string#2}; another hack is needed, since %D \type {#2} can be \type {\string} itself. +% \def\doregisterreference[#1]#2% +% {\doifvalue{\??id#1\c!referencing}\v!on +% {\pagereference[#1:#2]}} + \def\doregisterreference[#1]#2% {\doifvalue{\??id#1\c!referencing}\v!on - {\pagereference[#1:#2]}} + {\pagereference[#1:\strippedcsname#2]}} \def\dosetpageregisterletter#1#2% {\gdef\c!entryreference @@ -901,6 +933,10 @@ \endgroup \fi} +\def\doregisterregisterlanguage#1% + {\savesortlanguage{\getvalue{\??id#1\s!language}}% + \immediatewriteutility{r l {#1} {\getvalue{\??id#1\s!language}}}} + \def\dodefineregister[#1][#2]% {\setupregister[#1]% [\c!n=2, @@ -926,7 +962,11 @@ \c!unknownreference=\v!empty, \c!prefix=\v!both, \c!expansion=, - \c!keyexpansion=]% + \c!keyexpansion=, + \s!language=\currentmainlanguage]% + \doglobal\appendtoksonce + \doregisterregisterlanguage{#1}% + \to \everysavesortkeys \presetheadtext[#1=\Word{#1}]% \addutilityreset{#1}% \setvalue{#1}{\doregister{#1}}% diff --git a/tex/context/base/core-syn.tex b/tex/context/base/core-syn.tex index 9c291f156..ec866e18c 100644 --- a/tex/context/base/core-syn.tex +++ b/tex/context/base/core-syn.tex @@ -178,6 +178,10 @@ \dodocomplexsynonym[#2][#1#4]{#4}{#5}% \fi} +\def\doregistersynonymlanguage#1% + {\savesortlanguage{\getvalue{\??sm#1\s!language}}% + \immediatewriteutility{s l {#1} {\getvalue{\??sm#1\s!language}}}} + \def\dodefinesynonyms[#1][#2][#3][#4]% {\iffourthargument \unexpanded\def#4##1{\getsynonymmeaning{#1}{\??sm:#1:}{##1}}% @@ -199,7 +203,11 @@ \c!sample=,\c!hang=,\c!align=, \c!before=,\c!inbetween=,\c!after=, \c!indentnext=\v!no, - \c!expansion=]% + \c!expansion=, + \s!language=\currentmainlanguage]% + \doglobal\appendtoksonce + \doregistersynonymlanguage{#1}% + \to \everysavesortkeys \presetheadtext[#2=\Word{#2}]% changes the \if...argument \addutilityreset{#1}% \setvalue{\e!setup #2\e!endsetup}{\dodoubleargument\getparameters[\??sm#1]}% to be obsolete @@ -346,6 +354,10 @@ % if #3=\relax or \v!none, then no command but still protected +\def\doregistersortinglanguage#1% + {\savesortlanguage{\getvalue{\??so#1\s!language}}% + \immediatewriteutility{s l {#1} {\getvalue{\??so#1\s!language}}}} + \def\dodefinesorting[#1][#2][#3]% {\getparameters[\??so#1] [%\c!command=, % we test for defined ! @@ -354,7 +366,11 @@ \c!style=, \c!before=, \c!after=\endgraf, - \c!expansion=]% + \c!expansion=, + \s!language=\currentmainlanguage]% + \doglobal\appendtoksonce + \doregistersortinglanguage{#1}% + \to \everysavesortkeys \ifthirdargument \ConvertConstantAfter\doifnot{#3}\v!none {\ifx#3\relax \else diff --git a/tex/context/base/core-sys.tex b/tex/context/base/core-sys.tex index 3ca2241db..3d2fbd450 100644 --- a/tex/context/base/core-sys.tex +++ b/tex/context/base/core-sys.tex @@ -80,12 +80,12 @@ \fi \processaction [\@@svtype] - [ mswin=>\def\@@svline{\rawcharacter{13}\rawcharacter{10}}, % crlf - darwin=>\def\@@svline{\rawcharacter{13}}, % cr - \s!unknown=>\def\@@svline{\rawcharacter{10}}]% % lf + [ mswin=>\edef\@@svline{\rawcharacter{13}\rawcharacter{10}}, % crlf + darwin=>\edef\@@svline{\rawcharacter{13}}, % cr + \s!unknown=>\edef\@@svline{\rawcharacter{10}}]% % lf \splitjobfilename} -\def\@@svline{\rawcharacter{10}} % unix is the most critical/sensitive system +\edef\@@svline{\rawcharacter{10}} % unix is the most critical/sensitive system \def\systemendofline{\@@svline} diff --git a/tex/context/base/core-var.tex b/tex/context/base/core-var.tex index 9144606e9..54c9c52df 100644 --- a/tex/context/base/core-var.tex +++ b/tex/context/base/core-var.tex @@ -272,6 +272,7 @@ \newevery \everyendofpar \relax \newevery \everylistentry \relax \newevery \everymarking \relax +\newevery \everysavesortkeys \relax %D For shared \type {\everymath} and \type {\everydisplay}: diff --git a/tex/context/base/enco-fpl.tex b/tex/context/base/enco-fpl.tex index 0f9ba2966..2f90ad9c7 100644 --- a/tex/context/base/enco-fpl.tex +++ b/tex/context/base/enco-fpl.tex @@ -62,28 +62,30 @@ \stoplanguagespecifics -\startlanguagespecifics[\s!pl] - - \definesortkey {/a}{a}{a}{\k a} - \definesortkey {/A}{a}{a}{\k a} - \definesortkey {/c}{c}{a}{\'c} - \definesortkey {/C}{c}{a}{\'c} - \definesortkey {/e}{e}{a}{\k e} - \definesortkey {/E}{e}{a}{\k e} - \definesortkey {/l}{l}{a}{\l } - \definesortkey {/L}{l}{a}{\l } - \definesortkey {/n}{n}{a}{\'n} - \definesortkey {/N}{n}{a}{\'n} - \definesortkey {/o}{o}{a}{\'o} - \definesortkey {/O}{o}{a}{\'o} - \definesortkey {/s}{s}{a}{\'s} - \definesortkey {/S}{s}{a}{\'s} - \definesortkey {/x}{z}{a}{\'x} - \definesortkey {/X}{z}{a}{\'x} - \definesortkey {/z}{z}{b}{\.z} - \definesortkey {/Z}{z}{b}{\.z} - -\stoplanguagespecifics +% obsolete +% +% \startlanguagespecifics[\s!pl] +% +% \definesortkey {/a}{a}{a}{\k a} +% \definesortkey {/A}{a}{a}{\k a} +% \definesortkey {/c}{c}{a}{\'c} +% \definesortkey {/C}{c}{a}{\'c} +% \definesortkey {/e}{e}{a}{\k e} +% \definesortkey {/E}{e}{a}{\k e} +% \definesortkey {/l}{l}{a}{\l } +% \definesortkey {/L}{l}{a}{\l } +% \definesortkey {/n}{n}{a}{\'n} +% \definesortkey {/N}{n}{a}{\'n} +% \definesortkey {/o}{o}{a}{\'o} +% \definesortkey {/O}{o}{a}{\'o} +% \definesortkey {/s}{s}{a}{\'s} +% \definesortkey {/S}{s}{a}{\'s} +% \definesortkey {/x}{z}{a}{\'x} +% \definesortkey {/X}{z}{a}{\'x} +% \definesortkey {/z}{z}{b}{\.z} +% \definesortkey {/Z}{z}{b}{\.z} +% +% \stoplanguagespecifics \startencoding[pdfdoc] \startlanguagespecifics[pl]% hm diff --git a/tex/context/base/enco-ini.tex b/tex/context/base/enco-ini.tex index 9139aae75..70878656f 100644 --- a/tex/context/base/enco-ini.tex +++ b/tex/context/base/enco-ini.tex @@ -947,43 +947,17 @@ \def\startencoding {\dodoubleempty\dostartencoding} -% \def\dostartencoding[#1][#2]% encoding regime -% {\doifelsenothing{#1} -% {\let\stopencoding\relax} -% {%\protectfontcharacters % problematic in language loading -% %\showmessage\m!encodings1{#1}% -% \pushmacro\dohandleaccent % still needed? -% \pushmacro\dohandlecommand % still needed? -% \pushmacro\definesortkey -% \pushmacro\characterregime -% \pushmacro\doautosetregime -% \let\dohandleaccent\donthandleaccent % still needed? -% \let\dohandlecommand\donthandlecommand % still needed? -% \let\definesortkey\savesortkey -% \doifelsenothing{#2}% -% {\let\doautosetregime\gobbletwoarguments} -% {\def\characterregime{@#2@}}% -% \enableencoding[#1]% -% \def\stopencoding% -% {\popmacro\doautosetregime -% \popmacro\characterregime -% \popmacro\definesortkey -% \popmacro\dohandlecommand % still needed? -% \popmacro\dohandleaccent % still needed? -% \enableencoding[\s!default]% -% }}}% \unprotectfontcharacters}}} % ?? - \def\dostartencoding[#1][#2]% encoding regime {%\showmessage\m!encodings1{#1}% \pushmacro\characterencoding \pushmacro\characterregime \pushmacro\dohandleaccent % still needed? \pushmacro\dohandlecommand % still needed? - \pushmacro\definesortkey + %pushmacro\definesortkey \pushmacro\doautosetregime \let\dohandleaccent\donthandleaccent % still needed? \let\dohandlecommand\donthandlecommand % still needed? - \let\definesortkey\savesortkey + %let\definesortkey\savesortkey \edef\characterencoding{@#1@}% \doifelsenothing{#2}% {\let\doautosetregime\gobbletwoarguments} @@ -991,7 +965,7 @@ \def\stopencoding {\popmacro\doautosetregime - \popmacro\definesortkey + %popmacro\definesortkey \popmacro\dohandlecommand % still needed? \popmacro\dohandleaccent % still needed? \popmacro\characterregime @@ -1036,27 +1010,34 @@ %D This mechanism is currently being tested and subjected to %D changes! -\def\savesortkey#1#2#3#4% - {\let\flushsortkey\relax % important - \edef\!!stringa{sort:\characterencoding}% - \ifundefined\!!stringa - \let\!!stringb\empty - \else - \@EA\def\@EA\!!stringb\@EA{\csname\!!stringa\endcsname}% - \fi - \convertargument#1\to\asciiA \convertargument#2\to\asciiB - \convertargument#3\to\asciiC \convertargument#4\to\asciiD - \setevalue{\!!stringa}% - {\!!stringb\flushsortkey{\asciiA}{\asciiB}{\asciiC}{\asciiD}}} - -\def\definesortkey#1#2#3#4% - {} +%D THS CODE IS OBSOLETE -\def\flushsortkeys - {\enablelanguagespecifics[\currentlanguage]% - \getvalue{sort:\characterencoding}} +% \def\savesortkey#1#2#3#4% +% {\let\flushsortkey\relax % important +% \edef\!!stringa{sort:\characterencoding}% +% \ifundefined\!!stringa +% \let\!!stringb\empty +% \else +% \@EA\def\@EA\!!stringb\@EA{\csname\!!stringa\endcsname}% +% \fi +% \convertargument#1\to\asciiA \convertargument#2\to\asciiB +% \convertargument#3\to\asciiC \convertargument#4\to\asciiD +% \setevalue{\!!stringa}% +% {\!!stringb\flushsortkey{\asciiA}{\asciiB}{\asciiC}{\asciiD}}} +% +% \def\definesortkey#1#2#3#4% +% {} +% +% \def\flushsortkeys +% {\enablelanguagespecifics[\currentlanguage]% +% \getvalue{sort:\characterencoding}} +% +% \let\flushsortkey \relax -\let\flushsortkey\relax +\let\definesortkey\gobblefourarguments +\let\savesortkey \gobblefourarguments +\let\flushsortkeys\relax +\let\flushsortkey \relax %D \macros %D {defineaccent, definecharacter, definecommand} diff --git a/tex/context/base/enco-pol.tex b/tex/context/base/enco-pol.tex index d9f49a2dc..a012f0370 100644 --- a/tex/context/base/enco-pol.tex +++ b/tex/context/base/enco-pol.tex @@ -98,29 +98,31 @@ \stopencoding -\startencoding[pl0] - -\definesortkey {161} {a}{a}{\k a} \definesortkey {129} {a}{a}{\k a} -\definesortkey {162} {c}{a}{\'c} \definesortkey {130} {c}{a}{\'c} -\definesortkey {166} {e}{a}{\k e} \definesortkey {134} {e}{a}{\k e} -\definesortkey {170} {l}{a}{\l } \definesortkey {138} {l}{a}{\l } -\definesortkey {171} {n}{a}{\'n} \definesortkey {139} {n}{a}{\'n} -\definesortkey {177} {s}{a}{\'s} \definesortkey {145} {s}{a}{\'s} -\definesortkey {185} {z}{a}{\'z} \definesortkey {153} {z}{a}{\'z} -\definesortkey {187} {z}{b}{\.z} \definesortkey {155} {z}{b}{\.z} -\definesortkey {243} {o}{a}{\'o} \definesortkey {211} {o}{a}{\'o} - -\definesortkey {\'c} {c}{a}{\'c} \definesortkey {\'C} {c}{a}{\'c} -\definesortkey {\'n} {n}{a}{\'n} \definesortkey {\'N} {n}{a}{\'n} -\definesortkey {\'o} {o}{a}{\'o} \definesortkey {\'O} {o}{a}{\'o} -\definesortkey {\'s} {s}{a}{\'s} \definesortkey {\'S} {s}{a}{\'s} -\definesortkey {\'z} {z}{a}{\'z} \definesortkey {\'Z} {z}{a}{\'z} -\definesortkey {\.z} {z}{b}{\.z} \definesortkey {\.Z} {z}{b}{\.z} -\definesortkey {\k a}{a}{a}{\k a} \definesortkey {\k A}{a}{a}{\k a} -\definesortkey {\k e}{e}{a}{\k e} \definesortkey {\k E}{e}{a}{\k e} -\definesortkey {\l } {l}{a}{\l} \definesortkey {\L } {l}{a}{\l} - -\stopencoding +% obsolete +% +% \startencoding[pl0] +% +% \definesortkey {161} {a}{a}{\k a} \definesortkey {129} {a}{a}{\k a} +% \definesortkey {162} {c}{a}{\'c} \definesortkey {130} {c}{a}{\'c} +% \definesortkey {166} {e}{a}{\k e} \definesortkey {134} {e}{a}{\k e} +% \definesortkey {170} {l}{a}{\l } \definesortkey {138} {l}{a}{\l } +% \definesortkey {171} {n}{a}{\'n} \definesortkey {139} {n}{a}{\'n} +% \definesortkey {177} {s}{a}{\'s} \definesortkey {145} {s}{a}{\'s} +% \definesortkey {185} {z}{a}{\'z} \definesortkey {153} {z}{a}{\'z} +% \definesortkey {187} {z}{b}{\.z} \definesortkey {155} {z}{b}{\.z} +% \definesortkey {243} {o}{a}{\'o} \definesortkey {211} {o}{a}{\'o} +% +% \definesortkey {\'c} {c}{a}{\'c} \definesortkey {\'C} {c}{a}{\'c} +% \definesortkey {\'n} {n}{a}{\'n} \definesortkey {\'N} {n}{a}{\'n} +% \definesortkey {\'o} {o}{a}{\'o} \definesortkey {\'O} {o}{a}{\'o} +% \definesortkey {\'s} {s}{a}{\'s} \definesortkey {\'S} {s}{a}{\'s} +% \definesortkey {\'z} {z}{a}{\'z} \definesortkey {\'Z} {z}{a}{\'z} +% \definesortkey {\.z} {z}{b}{\.z} \definesortkey {\.Z} {z}{b}{\.z} +% \definesortkey {\k a}{a}{a}{\k a} \definesortkey {\k A}{a}{a}{\k a} +% \definesortkey {\k e}{e}{a}{\k e} \definesortkey {\k E}{e}{a}{\k e} +% \definesortkey {\l } {l}{a}{\l} \definesortkey {\L } {l}{a}{\l} +% +% \stopencoding %D Polish CP-1250 encoding. diff --git a/tex/context/base/font-uni.tex b/tex/context/base/font-uni.tex index a0d393025..026f767f8 100644 --- a/tex/context/base/font-uni.tex +++ b/tex/context/base/font-uni.tex @@ -38,11 +38,11 @@ \stopmessages \startmessages italian library: fonts - 21: l'uso di (pdf)eTeX è più sicuro + 21: l'uso di (pdf)eTeX è più sicuro \stopmessages \startmessages norwegian library: fonts - 21: å bruke (pdf)eTeX er tryggere + 21: Ã¥ bruke (pdf)eTeX er tryggere \stopmessages \startmessages french library: fonts diff --git a/tex/context/base/lang-ini.tex b/tex/context/base/lang-ini.tex index 6bfdabcef..469e90c53 100644 --- a/tex/context/base/lang-ini.tex +++ b/tex/context/base/lang-ini.tex @@ -96,16 +96,16 @@ \startmessages norwegian library: linguals title: språk - 1: orddelingsmønster -- for -- er lest inn (n=--,e=--,m=--) - 2: ingen orddelingsmønster -- for -- (n=--,e=--,m=--) (--,--) + 1: orddelingsmønster -- for -- er lest inn (n=--,e=--,m=--) + 2: ingen orddelingsmønster -- for -- (n=--,e=--,m=--) (--,--) 3: orddelingsdefinisjon -- for -- er lest inn (n=--,e=--,m=--) 4: ingen orddelingsdefinisjon -- for -- (n=--,e=--,m=--) - 5: orddelingsmønster for -- er ikke lest inn - 6: språk -- er udefinert - 7: språk spesifikk opsjon [--] introduserer et -- hopp - 8: språk spesifikk opsjon [--] problemfritt tilføyd - 9: språk -- er aktivt - 10: orddelingsmønster -- er lest inn + 5: orddelingsmønster for -- er ikke lest inn + 6: sprà k -- er udefinert + 7: sprà k spesifikk opsjon [--] introduserer et -- hopp + 8: sprà k spesifikk opsjon [--] problemfritt tilføyd + 9: sprà k -- er aktivt + 10: orddelingsmønster -- er lest inn \stopmessages \startmessages romanian library: linguals diff --git a/tex/context/base/m-r.tex b/tex/context/base/m-r.tex new file mode 100644 index 000000000..fe208cf75 --- /dev/null +++ b/tex/context/base/m-r.tex @@ -0,0 +1,159 @@ +%D \module +%D [ file=m-r, +%D version=2006.06.06, +%D title=\CONTEXT\ Modules, +%D subtitle=R Support, +%D author={Johan Sandblom \& Hans Hagen}, +%D date=\currentdate, +%D copyright={PRAGMA / Johan Sandblom}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\unprotect + +%D The following R-processor is a variation on Johan Sandblom's +%D prototype. +%D +%D We can combine both variants in one macro definition. Also, we +%D can minimize the number of runs by checking for a change. + +%D \starttyping +%D \newcounter\Rnumber +%D \newtoks\everyR +%D +%D \appendtoks +%D \obeylines +%D \to \everyR +%D +%D \def\startR {\dostartR\stopR \plusone} +%D \def\startRhidden{\dostartR\stopRhidden\zerocount} +%D +%D \def\dostartR#1#2% +%D {\bgroup +%D \ifcase#2\relax\let\typeRout\relax\fi +%D \obeylines +%D \catcode`\%=\@@letter +%D \catcode`\#=\@@letter +%D \def\dostartR##1#1% +%D {\doglobal\increment\Rnumber +%D \edef\Rfile{\bufferprefix R-\Rnumber}% +%D \bgroup +%D \the\everyR +%D \def\par{\rawcharacter{10}}% +%D \immediate\openout\scratchwrite=\Rfile.r +%D \immediate\write\scratchwrite{##1}% +%D \immediate\closeout\scratchwrite +%D \egroup +%D \doifmode{*\v!first}\runR +%D \typefile{\Rfile.rout}% +%D \egroup}% +%D \doifnextcharelse\relax\dostartR\dostartR} +%D +%D \def\runR +%D {\executesystemcommand{texmfstart +%D --ifchanged=\Rfile.r bin:R +%D "-q --save --restore < \Rfile.r > \Rfile.rout"}} +%D \stoptyping + +%D JS: The call to R has \type {-q} in order to prevent banner, +%D \type {--save} to make sure it saves the workspace after the run, +%D \type {--restore} to make sure it reads any workspace from a +%D previous session. + +%D An easier and better solution is to use the buffering mechanisms: + +\def\Rbufferprefix{r-} +\newcounter\nofRfiles + +\def\Rfile{\TEXbufferfile{\Rbufferprefix\nofRfiles}}% + +\def\startR + {\doglobal\increment\nofRfiles + \dostartbuffer[\Rbufferprefix\nofRfiles][startR][stopR]} + +\def\stopR + {\doifmode{*\v!first}\runR + \typefile{\Rfile.out}} + +\def\startRhidden + {\doglobal\increment\nofRfiles + \dostartbuffer[\Rbufferprefix\nofRfiles][startRhidden][stopRhidden]} + +\def\stopRhidden + {\doifmode{*\v!first}\runR} + +\def\runR + {\executesystemcommand{texmfstart +% --ifchanged=\Rfile\space bin:R + --ifchanged=\Rfile\space --direct R + "-q --save --restore < \Rfile\space > \Rfile.out"}} + +\protect \doifnotmode{demo}{\endinput} + +% Johan's test file: + +\starttext + +\startR +a <- "bla" +b <- "blabla" +ls() +\stopR + +bla bla + +\startRhidden +rm(list=ls()) +save.image() +\stopRhidden + +more bla + +\startR +ls() +ushape <- c(rexp(500000), 12-rexp(500000)) +pdf("ushape.pdf") +par(mfrow=c(1,2)) +hist(ushape) +plot(density(ushape), main="Density") +dev.off() +\stopR + +\input tufte \par \input knuth + +\startR +x <- rnorm(900) +y <- rexp(900) +# test comment +f <- gl(9,9,900) +summary(aov(y~x+Error(f))) +library(lattice) +pdf("lattice.pdf") +xyplot(y~x|f) +dev.off() +\stopR + +\placefigure{}{\externalfigure[lattice]} +\placefigure{}{\externalfigure[ushape]} + +\input tufte + +\startR +(test <- ".*\\\\ []{}=?!+%#|<|>@$") +cat(test) +\stopR + +\input bryson \par \input knuth + +\startR +a.df <- data.frame(a=1:2, b=rnorm(2)) +a.df$a +testfunction <- function(a=NULL, ...) { + for(i in 1:length(a)) { + gsub(a[[i]], "([a-r]|[A-R])", "bla")} + print(a)} +\stopR + +\stoptext diff --git a/tex/context/base/meta-pdf.tex b/tex/context/base/meta-pdf.tex new file mode 100644 index 000000000..1c76075a9 --- /dev/null +++ b/tex/context/base/meta-pdf.tex @@ -0,0 +1,3203 @@ +%D \module +%D [ file=meta-pdf, +%D version=2006.06.07, +%D title=\CONTEXT\ Support Macros, +%D subtitle=\METAPOST\ to \PDF\ conversion, +%D author=Hans Hagen \& others (see text), +%D date=\currentdate, +%D copyright=\PRAGMA] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D In due time this file will replace \type {supp-pdf} and +%D \type {supp-mpe}. + +\input supp-pdf +\input supp-mpe + +\endinput + +%D To be tested: texopt.rb on this file. + +%D Prelude to an optimized version: + +%D \module +%D [ file=supp-pdf, +%D version=2004.12.16, +%D title=\CONTEXT\ Support Macros, +%D subtitle=\METAPOST\ to \PDF\ conversion, +%D author=Hans Hagen \& others (see text), +%D date=\currentdate, +%D copyright=\PRAGMA] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D These macros are written as generic as possible. Some +%D general support macro's are loaded from a small module +%D especially made for non \CONTEXT\ use. In this module I +%D use a matrix transformation macro written by Tanmoy +%D Bhattacharya. Thanks to extensive testing by Sebastian +%D Ratz I was able to complete this module within reasonable +%D time. This module has support for \METAPOST\ extensions +%D built in. +%D +%D Daniel H. Luecking came up with a better (more precise) +%D transformation method. You can recognize his comment by +%D his initials. (We keep the old code around because it's a +%D nice illustration on how a module like this evolves.) + +% Beware, we cannot use \zeropoint here since it may be +% defined in the range \dimen 0 - 20 which we happen to use +% as scratch registers; inside context we may consider +% using dedicated registers. + +%D This module handles some \PDF\ conversion and insertions +%D topics. By default, the macros use the \PDFTEX\ primitive +%D \type{\pdfliteral} when available. Since \PDFTEX\ is now the +%D default engine for \TEX\ distributions, we need a more complex +%D test. + +\writestatus{loading}{Context Support Macros / PDF (2004.03.26)} + +\unprotect + +\ifx\PDFcode\undefined + \ifx\pdfliteral\undefined + \def\PDFcode#1{\special{PDF: #1}} + \else\ifx\pdfoutput\undefined + \def\PDFcode#1{\special{PDF: #1}} + \else\ifcase\pdfoutput + \def\PDFcode#1{\special{PDF: #1}} + \else % pdftex as well as in pdf mode + \let\PDFcode\pdfliteral + \fi\fi\fi +\else + % we probably use context +\fi + +%D First we define a handy constant: + +\bgroup \catcode`\%=\@@other \xdef\letterpercent{\string%} \egroup + +%D \macros +%D {pdfimage,pdfimages,pdfclippedimage} +%D +%D Starting with pdftex version 14, images are included more +%D natural to the form embedding. This enables alternative +%D images to be embedded. +%D +%D \starttyping +%D \pdfimage <optional dimensions> {file} +%D \pdfimages <optional dimensions> {high res file} {low res file} +%D \stoptyping +%D +%D The first one replaces the pre||version||14 original, +%D while the latter provides alternative images. +%D +%D The next macro is dedicated to Maarten Gelderman, who +%D needed to paste prepared \PDF\ pages into conference +%D proceedings. +%D +%D \starttyping +%D \pdfclippedimage <optional dimensions> {file} {l} {r} {t} {b} +%D \stoptyping + +\ifx\pdftexversion\undefined \else \ifnum\pdftexversion>13 + + \def\pdfimage#1#% + {\dopdfimage{#1}} + + \def\dopdfimage#1#2% + {\immediate\pdfximage#1{#2}% + \pdfrefximage\pdflastximage} + + \def\pdfimages#1#% + {\dopdfimages{#1}} + + \def\dopdfimages#1#2#3% + {\immediate\pdfximage#1{#2}% + \immediate\pdfobj + {[ << /Image \the\pdflastximage\space0 R + /DefaultForPrinting true >> ]}% + \immediate\pdfximage#1 + attr {/Alternates \the\pdflastobj\space0 R}{#3}% + \pdfrefximage\pdflastximage} + + \def\pdfclippedimage#1#% specs {file}{left}{right}{top}{bottom} + {\dopdfclippedimage{#1}} + + \def\dopdfclippedimage#1#2#3#4#5#6% + {\bgroup + \pdfximage#1{#2}% + \setbox\scratchbox\hbox + {\pdfrefximage\pdflastximage}% + \hsize\wd\scratchbox + \advance\hsize -#3% + \advance\hsize -#4% + \vsize\ht\scratchbox + \advance\vsize -#5% + \advance\vsize -#6% + \setbox\scratchbox\vbox to \vsize + {\vskip-#5\hbox to \hsize{\hskip-#3\box\scratchbox\hss}}% + \pdfxform\scratchbox + \pdfrefxform\pdflastxform + \egroup} + +\fi \fi + +%D If you want to save a few hash entries, you may prefer the +%D less readable alternatives, like: +%D +%D \starttyping +%D \def\pdfimage#1#% This one is less readable but needs no additional +%D {\bgroup % hash entry for the second stage macro. +%D \def\pdfimage##1% +%D {\immediate\pdfximage##1{#2}% +%D \pdfrefximage\pdflastximage\egroup}} +%D \stoptyping + +%D \macros +%D {convertMPtoPDF} +%D +%D The next set of macros implements \METAPOST\ to \PDF\ +%D conversion. Because we want to test as fast as possible, we +%D first define the \POSTSCRIPT\ operators that \METAPOST\ +%D uses. We don't define irrelevant ones, because these are +%D skipped anyway. + +%D The converter can be made a bit faster by replacing the +%D two test macros (the ones with the many \type {\if's}) by +%D a call to named branch macros (something \typ {\getvalue +%D {xPSmoveto}}. For everyday documents with relatively +%D small graphics the gain in speed can be neglected. + +\def \PScurveto {curveto} +\def \PSlineto {lineto} +\def \PSmoveto {moveto} +\def \PSshowpage {showpage} +\def \PSnewpath {newpath} +\def \PSfshow {fshow} +\def \PSclosepath {closepath} +\def \PSfill {fill} +\def \PSstroke {stroke} +\def \PSclip {clip} +\def \PSrlineto {rlineto} +\def \PSsetlinejoin {setlinejoin} +\def \PSsetlinecap {setlinecap} +\def \PSsetmiterlimit {setmiterlimit} +\def \PSsetgray {setgray} +\def \PSsetrgbcolor {setrgbcolor} +\def \PSsetcmykcolor {setcmykcolor} +\def \PSsetdash {setdash} +\def \PSgsave {gsave} +\def \PSgrestore {grestore} +\def \PStranslate {translate} +\def \PSscale {scale} +\def \PSconcat {concat} +\def \PSdtransform {dtransform} +\def \PSsetlinewidth {setlinewidth} +\def \PSpop {pop} + +\def \PSnfont {nfont} % was needed for TUG98 proceedings +\def \PSspecial {special} % extensions to MetaPost + +%D A previous version set \type {%} to ignore, which +%D simplified the following definitions. At the start of +%D conversion the percent character was made active again. +%D Because the whole graphic is one paragraph (there are no +%D empty lines) this does not give the desired effect. This +%D went unnoticed untill Scott Pakin sent me a test file +%D percent characters in a string. So, from now on we have +%D to prefix the following strings with percentages. + +%D Some day I'll figure out a better solution (line by line reading +%D using \ETEX). + +\edef \PSBoundingBox {\letterpercent\letterpercent BoundingBox:} +\edef \PSHiResBoundingBox {\letterpercent\letterpercent HiResBoundingBox:} +\edef \PSExactBoundingBox {\letterpercent\letterpercent ExactBoundingBox:} +\edef \PSMetaPostSpecial {\letterpercent\letterpercent MetaPostSpecial:} +\edef \PSMetaPostSpecials {\letterpercent\letterpercent MetaPostSpecials:} +\edef \PSPage {\letterpercent\letterpercent Page:} + +%D By the way, the \type {setcmykcolor} operator is not +%D output by \METAPOST\ but can result from converting the +%D \cap{RGB} color specifications, as implemented in +%D \type{supp-mps}. + +%D In \POSTSCRIPT\ arguments precede the operators. Due to the +%D fact that in some translations we need access to those +%D arguments, and also because sometimes we have to skip them, +%D we stack them up. The stack is one||dimensional for non path +%D operators and two||dimensional for operators inside a path. +%D This is because we have to save the whole path for +%D (optional) postprocessing. Values are pushed onto the stack +%D by: +%D +%D \starttyping +%D \setMPargument {value} +%D \stoptyping +%D +%D They can be retrieved by the short named macros: +%D +%D \starttyping +%D \gMPa {number} +%D \gMPs {number} +%D \stoptyping +%D +%D When scanning a path specification, we also save the +%D operator, using +%D +%D \starttyping +%D \setMPkeyword {n} +%D \stoptyping +%D +%D The path drawing operators are coded for speed: \type{clip}, +%D \type{stroke}, \type{fill} and \type{fillstroke} become +%D 1, 2, 3 and~4. +%D +%D When processing the path this code can be retrieved +%D using +%D +%D \starttyping +%D \getMPkeyword % {n} +%D \stoptyping +%D +%D When setting an argument, the exact position on the stack +%D depends on the current value of the \COUNTERS\ +%D \type{\nofMPsegments} and \type{\nofMParguments}. + +\newcount\nofMPsegments +\newcount\nofMParguments + +%D These variables hold the coordinates. The argument part of +%D the stack is reset by: +%D +%D \starttyping +%D \resetMPstack +%D \stoptyping +%D +%D We use the prefix \type{@@MP} to keep the stack from +%D conflicting with existing macros. To speed up things a bit +%D more, we use the constant \type{\@@MP}. + +\def\@@MP{@@MP} + +\def\setMPargument% #1% + {\advance\nofMParguments \plusone + \expandafter\def + \csname\@@MP\the\nofMPsegments\the\nofMParguments\endcsname} % {#1} + +\def\letMPargument + {\advance\nofMParguments \plusone + \expandafter\let + \csname\@@MP\the\nofMPsegments\the\nofMParguments\endcsname} + +\def\setMPsequence#1 % + {\advance\nofMParguments \plusone + \expandafter\def + \csname\@@MP\the\nofMPsegments\the\nofMParguments\endcsname{#1}% + \handleMPsequence} + +\def\gMPa#1% + {\csname\@@MP0\number#1\endcsname} + +\def\gMPs#1% + {\csname\@@MP\the\nofMPsegments\number#1\endcsname} + +\def\dogMPa#1% + {\@EAEAEA\do\csname\@@MP0\number#1\endcsname} + +\def\setMPkeyword#1 % + {\expandafter\def\csname\@@MP\the\nofMPsegments0\endcsname{#1}% + \advance\nofMPsegments \plusone + \nofMParguments\zerocount} + +\def\getMPkeyword% #1% + {\csname\@@MP\the\nofMPsegments0\endcsname} % {\csname\@@MP#10\endcsname} + +\def\docleanupMPargument#1% we need this because args can have [ or ] pre/appended + {\expandafter\edef\csname\@@MP\the\nofMPsegments\number#1\endcsname + {\csname\@@MP\the\nofMPsegments\number#1\endcsname}} + +%D When we reset the stack, we can assume that all further +%D comment is to be ignored and handled in strings. +%D By redefining the reset macro after the first call, we +%D save some run time. Only use this macro after all +%D comments are processed and use the simple alternative +%D when dealing with comments. + +\def\doresetMPstack + {\nofMParguments\zerocount} + +\def\resetMPstack + {\let\handleMPgraphic\handleMPendgraphic + \let\resetMPstack\doresetMPstack + \resetMPstack} + +%D The arguments are saved with the preceding command +%D \type{\do}. By default this command expands to nothing, but +%D when we deal with strings it's used to strip off the +%D \type{(} and \type{)}. +%D +%D Strings are kind of tricky, because characters can be +%D passed verbatim \type{(hello)}, by octal number +%D \type{(\005)} or as command \type{(\()}. We therefore +%D cannot simply ignore \type{(} and \type{)}, the way we do +%D with \type{[} and \type{]}. Another complication is that +%D strings may contain characters that normally have a +%D special meaning in \TEX, like \type{$} and \type{{}}. +%D +%D A previous solution made \type{\} an active character and +%D let it look ahead for a number or characters. We had to +%D abandon this scheme because of the need for verbatim +%D support. The next solution involved some \CATCODE\ +%D trickery but works well. + +\def\octalMPcharacter#1#2#3% + {\char'#1#2#3\relax} + +%D curly braces and squarly brackets are stored in the argument stack +%D as part of strings, for instance in: +%D +%D \starttyping +%D /fshow {exch findfont exch scalefont setfont show}bind def +%D [3 3 ] 0 setdash +%D \stoptyping +%D +%D but we need to keep them in situation like +%D +%D \starttyping +%D ([bla bla] bla bla) ec-lmr10 9.96265 fshow +%D ({bla bla} bla bla) ec-lmr10 9.96265 fshow +%D \stoptyping +%D +%D So, when we store the snippets, we keep the special tokens, and +%D when needed we either ignore or obey them + +\bgroup +\catcode`\|=\@@comment +\catcode`\%=\@@active +\catcode`\[=\@@active +\catcode`\]=\@@active +\catcode`\{=\@@active +\catcode`\}=\@@active +\catcode`B=\@@begingroup +\catcode`E=\@@endgroup +\gdef\keepMPspecials| + B\let%\letterpercent| + \def[B\noexpand[E| + \def]B\noexpand]E| + \def{B\noexpand{E| + \def}B\noexpand}EE +\gdef\ignoreMPspecials| + B\let%\letterpercent| + \def[BE| + \def]BE| + \def{BE| + \def}BEE +\gdef\obeyMPspecials| + B\def%B\char 37\relax E| + \def[B\char 91\relax E| + \def]B\char 93\relax E| + \def{B\char123\relax E| + \def}B\char125\relax EE +\gdef\setMPspecials| + B\setnaturalcatcodes + \catcode`\\=\@@escape + \catcode`\%=\@@active + \catcode`\[=\@@active + \catcode`\]=\@@active + \catcode`\{=\@@active + \catcode`\}=\@@active + \lccode`\-=0 | latex sets this to `\- + \lccode`\%=`\% | otherwise it's seen as a number + \def\(B\char40\relax E| + \def\)B\char41\relax E| + \def\\B\char92\relax E| + \def\0B\octalMPcharacter0E| + \def\1B\octalMPcharacter1E| + \def\2B\octalMPcharacter2E| + \def\3B\octalMPcharacter3E| + \def\4B\octalMPcharacter4E| + \def\5B\octalMPcharacter5E| + \def\6B\octalMPcharacter6E| + \def\7B\octalMPcharacter7E| + \def\8B\octalMPcharacter8E| + \def\9B\octalMPcharacter9EE +\egroup + +%D We use the comment symbol as a sort of trigger. Beware! +%D The whole graphic is seen as on eparagraph, which means +%D that we cannot change the catcodes in between. + +\bgroup +\catcode`\%=\@@active +\gdef\startMPscanning{\let%=\startMPconversion} +\egroup + +%D In earlier versions we used the sequence +%D +%D \starttyping +%D \expandafter\handleMPsequence\input filename\relax +%D \stoptyping +%D +%D Persistent problems in \LATEX\ however forced us to use a +%D different scheme. Every \POSTSCRIPT\ file starts with a +%D \type{%}, so we temporary make this an active character +%D that starts the scanning and redefines itself. (The problem +%D originates in the redefinition by \LATEX\ of the +%D \type{\input} primitive.) + +\def\startMPconversion + {\keepMPspecials + \handleMPsequence} + +%D Here comes the main loop. Most arguments are numbers. This +%D means that they can be recognized by their \type{\lccode}. +%D This method saves a lot of processing time. We could +%D speed up the conversion by handling the \type{path} +%D seperately. + +\def\@EAEAEA{\expandafter\expandafter\expandafter} % to be sure + +\def\dohandleMPsequence#1% + {\ifdone + \ifcase\lccode`#1\relax + \@EAEAEA\dohandleMPsequenceA + \else + \@EAEAEA\dohandleMPsequenceB + \fi + \else + \@EA\dohandleMPsequenceC + \fi#1} + +\let\dohandleMPsequenceA\setMPsequence + +\def\dohandleMPsequenceB#1 % + {\edef\somestring{#1}% + \ifx\somestring\PSmoveto + \edef\lastMPmoveX{\gMPa1}% + \edef\lastMPmoveY{\gMPa2}% + \PDFcode{\!MPgMPa1 \!MPgMPa2 m}% + \resetMPstack + \else\ifx\somestring\PSnewpath + \let\handleMPsequence\handleMPpath + \else\ifx\somestring\PSgsave + \PDFcode{q}% + \resetMPstack + \else\ifx\somestring\PSgrestore + \PDFcode{Q}% + \resetMPstack + \else\ifx\somestring\PSdtransform % == setlinewidth + \let\handleMPsequence\handleMPdtransform + % after that we will encounter more tokens until setlinewidth+pop + % or pop+setlinewidth which we catch next; we explicitly need to + % reset the stack since [] n setdash may follow; a more clever + % approach would be to read on till the condition is met, but it's + % the only pop / setlinewidth we will encounter so ... + \else\ifx\somestring\PSsetlinewidth + % already handled in dtransform + \resetMPstack + \else\ifx\somestring\PSpop + % already handled in dtransform + \resetMPstack + \else\ifx\somestring\PSconcat + \cleanupMPconcat + \PDFcode{\gMPa1 \gMPa2 \gMPa3 \gMPa4 \gMPa5 \gMPa6 cm}% + \resetMPstack + \else\ifx\somestring\PSsetrgbcolor + \handleMPrgbcolor + \resetMPstack + \else\ifx\somestring\PSsetcmykcolor + \handleMPcmykcolor + \resetMPstack + \else\ifx\somestring\PSsetgray + \handleMPgraycolor + \resetMPstack + \else\ifx\somestring\PStranslate + \PDFcode{1 0 0 1 \gMPa1 \gMPa2 cm}% + \resetMPstack + \else\ifx\somestring\PSsetdash + \handleMPsetdash + \resetMPstack + \else\ifx\somestring\PSsetlinejoin + \PDFcode{\gMPa1 j}% + \resetMPstack + \else\ifx\somestring\PSsetmiterlimit + \PDFcode{\gMPa1 M}% + \resetMPstack + \else\ifx\somestring\PSfshow + \PDFcode{n}% + \handleMPfshow + \resetMPstack + \else\ifx\somestring\PSsetlinecap + \PDFcode{\gMPa1 J}% + \resetMPstack + \else\ifx\somestring\PSrlineto + \PDFcode{\!MP\lastMPmoveX\space\!MP\lastMPmoveY\space l S}% + \resetMPstack + \else\ifx\somestring\PSscale + \PDFcode{\gMPa1 0 0 \gMPa2 0 0 cm}% + \resetMPstack + \else\ifx\somestring\PSspecial + \handleMPspecialcommand + \resetMPstack + \else + \handleMPgraphic% {#1}% + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \handleMPsequence} + +\def\dohandleMPsequenceC#1 % + {\edef\somestring{#1}% + \handleMPgraphic % {#1}% + \handleMPsequence} + +%D Since colors are not sensitive to transformations, they +%D are sometimes used for signaling. Therefore, we handle them +%D separately. The next macro can be redefined if needed. + +\def\handleMPrgbcolor + {\PDFcode{\!MPgMPa1 \!MPgMPa2 \!MPgMPa3 rg + \!MPgMPa1 \!MPgMPa2 \!MPgMPa3 RG}} + +\def\handleMPcmykcolor + {\PDFcode{\!MPgMPa1 \!MPgMPa2 \!MPgMPa3 \!MPgMPa4 k + \!MPgMPa1 \!MPgMPa2 \!MPgMPa3 \!MPgMPa4 K}} + +\def\handleMPgraycolor + {\PDFcode{\!MPgMPa1 g + \!MPgMPa1 G}} + +\def\handleMPspotcolor + {\PDFcode{0 g + 0 G}} + +%D Beginning and ending the graphics is taken care of by the +%D macro \type{\handleMPgraphic}, which is redefined when +%D the first graphics operator is met. + +\def\handleMPendgraphic % #1% + {\ifx\somestring\PSshowpage + \let\handleMPsequence\finishMPgraphic + \else + \letMPargument\somestring % {#1}% + \fi} + +\def\handleMPbegingraphic % #1% + {\ifx\somestring\PSBoundingBox + \def\handleMPsequence{\handleMPboundingbox1}% + \else\ifx\somestring\PSHiResBoundingBox + \def\handleMPsequence{\handleMPboundingbox2}% + \else\ifx\somestring\PSExactBoundingBox + \def\handleMPsequence{\handleMPboundingbox3}% + \else\ifx\somestring\PSshowpage + \let\handleMPsequence\finishMPgraphic + \else\ifx\somestring\PSPage + \let\handleMPsequence\handleMPpage + \else\ifx\somestring\PSMetaPostSpecials + \let\handleMPsequence\handleMPspecialscomment + \else\ifx\somestring\PSMetaPostSpecial + \let\handleMPsequence\handleMPspecialcomment + \else + \letMPargument\somestring % {#1}% + \fi\fi\fi\fi\fi\fi\fi} + +\let\handleMPgraphic=\handleMPbegingraphic + +%D We check for three kind of bounding boxes: the normal one +%D and two high precision ones: +%D +%D \starttyping +%D BoundingBox: llx lly ucx ucy +%D HiResBoundingBox: llx lly ucx ucy +%D ExactBoundingBox: llx lly ucx ucy +%D \stoptyping +%D +%D The original as well as the recalculated dimensions are +%D saved for later use. + +\newif\ifskipemptyMPgraphic \skipemptyMPgraphicfalse + +\chardef\currentMPboundingbox=0 + +\def\handleMPboundingbox#1#2 #3 #4 #5 + {\ifnum#1>\currentMPboundingbox + \xdef\MPllx{#2}\xdef\MPlly{#3}% + \xdef\MPurx{#4}\xdef\MPury{#5}% + \dimen0=#2\onepoint + \dimen0=-\MPxscale\dimen0 + \dimen2=#3\onepoint + \dimen2=-\MPyscale\dimen2 + \xdef\MPxoffset{\withoutpt\the\dimen0}% + \xdef\MPyoffset{\withoutpt\the\dimen2}% + \dimen0=#2\onebasepoint + \dimen0=-\dimen0 + \dimen2=#3\onebasepoint + \dimen2=-\dimen2 + \advance\dimen0 #4\onebasepoint + \dimen0=\MPxscale\dimen0 + \xdef\MPwidth{\the\dimen0}% + \advance\dimen2 #5\onebasepoint + \xdef\MPyshift{\the\dimen2}% unscaled + \dimen2=\MPyscale\dimen2 + \xdef\MPheight{\the\dimen2}% + \chardef\currentMPboundingbox#1\relax + \fi + \doresetMPstack + \let\handleMPsequence\dohandleMPsequence + \let\next\handleMPsequence + \ifskipemptyMPgraphic + \ifdim\MPheight=\zeropoint\relax\ifdim\MPwidth=\zeropoint\relax + \def\next{\endinput\finishMPgraphic}% + \fi\fi + \fi + \next} + +%D Unless defined otherwise, we simply ignore specialcomments. + +\def\handleMPspecialcomment + {\doresetMPstack + \let\handleMPsequence\dohandleMPsequence + \handleMPsequence} + +\let\handleMPspecialscomment\handleMPspecialcomment + +%D We use the \type{page} comment as a signal that +%D stackbuilding can be started. + +\def\handleMPpage #1 #2 + {\doresetMPstack + \donetrue + \let\handleMPsequence\dohandleMPsequence + \handleMPsequence} + +%D The same applies to the special extensions. + +\def\handleMPspecialcommand + {\doresetMPstack + \let\handleMPsequence\dohandleMPsequence + \handleMPsequence} + +%D \METAPOST\ draws its dots by moving to a location and +%D invoking \type{0 0 rlineto}. This operator is not +%D available in \PDF. Our solution is straightforward: we draw +%D a line from $(current\_x, current\_y)$ to itself. This +%D means that the arguments of the preceding \type{moveto} have +%D to be saved. + +\def\lastMPmoveX{0} +\def\lastMPmoveY{0} + +%D These saved coordinates are also used when we handle the +%D texts. Text handling proved to be a bit of a nuisance, but +%D finally I saw the light. It proved that we also had to +%D take care of \type{(split arguments)}. + +\def\setMPfshowfont#1#2% + {\font\temp=#1\space at #2\relax\temp} + +\let\MPfshowcommand\empty + +\def\dohandleMPfshow + {\bgroup + \setbox\scratchbox\hbox + {\obeyMPspecials + \let\ \relax % mp breaks long lines and appends a \ + \edef\size{\gMPa\nofMParguments}% + \ifx\size\PSnfont % round font size (to pt) + \advance\nofMParguments \minusone + \expandafter\scratchdimen\gMPa\nofMParguments\onepoint\relax + \ifdim\scratchdimen<\onepoint + \def\size{1pt}% + \else + \advance\scratchdimen .5\onepoint + \def\size##1.##2\relax{\def\size{##1pt}}% + \expandafter\size\the\scratchdimen\relax + \fi + \else + \edef\size{\size bp}% + \fi + \advance\nofMParguments \minusone + %\font\temp=\gMPa\nofMParguments\space at \size + \let\temp\relax % to be sure + \setMPfshowfont{\gMPa\nofMParguments}\size + \advance\nofMParguments \minusone + \temp + \MPfshowcommand + {\ifnum\nofMParguments=\plusone + \def\do(##1){##1}% + \dogMPa1% + \else + % we need to catch ( a ) (a a a) (\123 \123 \123) etc + \scratchcounter\plusone + \def\dodo##1% Andreas Fieger's bug: (\304...) + {\edef\!!stringa{##1\empty\empty}% and another one: ( 11) -> \ifx 11 + \ifx\!!stringa\MPspacechar\MPspacechar\else\expandafter##1\fi}% + \def\do(##1{\dodo{##1}}% + \dogMPa\scratchcounter\MPspacechar + \let\do\relax + \loop + \advance\scratchcounter \plusone + \ifnum\scratchcounter<\nofMParguments\relax + \gMPa\scratchcounter\MPspacechar + \repeat + \def\do##1){\dodo{##1}}% + \dogMPa\scratchcounter + \fi + \unskip}}% + % + % this fails in some versions of pdftex + % + % \dimen0=\lastMPmoveY bp + % \advance\dimen0 by \ht0 + % \ScaledPointsToBigPoints{\number\dimen0}\lastMPmoveY + % \PDFcode{n q 1 0 0 1 \lastMPmoveX\space\lastMPmoveY\space cm}% + % \dimen0=\ht0 + % \advance\dimen0 by \dp0 + % \box0 + % \vskip-\dimen0 + % \PDFcode{Q}% + % \egroup} + % + \setbox\scratchbox\hbox + {\hskip\lastMPmoveX\onebasepoint\raise\lastMPmoveY\onebasepoint\box\scratchbox}% + \ht\scratchbox\zeropoint + \dp\scratchbox\zeropoint + \wd\scratchbox\zeropoint + \box\scratchbox + \egroup} + +\let\handleMPfshow\dohandleMPfshow % so we can overload this one later + +%D You could consider the following definition to be the most +%D natural one. + +% \def\MPspacechar{\space} % normal case + +\def\MPspacechar{\char32\relax} % old solution does not work with math + +%D However, the following implementation is more robust, since +%D some fonts have funny visible spaces in the space slot. This +%D gives a mismatch between the space that \METAPOST\ took into +%D account and the \quote {natural} space. This only happens in +%D labels, since \type {btex}||\type {etex} thingies don't have +%D spaces. This phenomena showed up when preparing the +%D \METAFUN\ manual, where Palatino fonts are used. We can +%D safely assume that \METAPOST\ considers \type {\char32} to +%D be the space. + +\def\MPspacechar{\setbox\scratchbox\hbox{\char32}\kern\wd\scratchbox} + +%D Well, this does not work with math fonts, so: + +\def\MPspacechar{\char32\relax} + +%D Most operators are just converted and keep their +%D arguments. Dashes however need a bit different treatment, +%D otherwise \PDF\ viewers complain loudly. Another +%D complication is that one argument comes after the \type{]}. +%D When reading the data, we simply ignore the array boundary +%D characters. We save ourselves some redundant newlines and +%D at the same time keep the output readable by packing the +%D literals. + +\def\handleMPsetdash + {\bgroup + \ignoreMPspecials + \def\somestring{[}% + \scratchcounter\plusone + \loop + \ifnum\scratchcounter<\nofMParguments + \edef\somestring{\somestring\space\gMPa\scratchcounter}% + \advance\scratchcounter \plusone + \repeat + \edef\somestring{\somestring]\gMPa\scratchcounter\space d}% + \PDFcode{\somestring}% + \egroup} + +%D The \type{setlinewidth} commands looks a bit complicated. There are +%D two alternatives, that result in a similar look in both +%D $x$- and $y$-dorection. As John Hobby says: +%D +%D \startnarrower \switchtobodyfont[ss] +%D \starttyping +%D x 0 dtransform exch truncate exch idtransform pop setlinewidth +%D 0 y dtransform truncate idtransform setlinewidth pop +%D \stoptyping +%D +%D These are just fancy versions of \type{x setlinewidth} and +%D \type{y setlinewidth}. The \type{x 0 ...} form is used if +%D the path is {\em primarily vertical}. It rounds the width +%D so that vertical lines come out an integer number of pixels +%D wide in device space. The \type{0 y ...} form does the same +%D for paths that are {\em primarily horizontal}. The reason +%D why I did this is Knuth insists on getting exactly the +%D widths \TEX\ intends for the horizontal and vertical rules +%D in \type{btex...etex} output. (Note that PostScript scan +%D conversion rules cause a horizontal or vertical line of +%D integer width $n$ in device space to come out $n+1$ pixels +%D wide, regardless of the phase relative to the pixel grid.) +%D \stopnarrower +%D +%D The common operator in these sequences is \type{dtransform}, +%D so we can use this one to trigger setting the linewidth. + +\def\handleMPdtransform + {\ifdim\gMPa1\onepoint>\zeropoint + \PDFcode{\gMPa1 w}% + \def\next##1 ##2 ##3 ##4 ##5 ##6 {\handleMPsequence}% + \else + \PDFcode{\gMPa2 w}% + \def\next##1 ##2 ##3 ##4 {\handleMPsequence}% + \fi + \let\handleMPsequence\dohandleMPsequence + \resetMPstack + \next} + +%D The most complicated command is \type{concat}. \METAPOST\ +%D applies this operator to \type{stroke}. At that moment the +%D points set by \type{curveto} and \type{moveto}, are already +%D fixed. In \PDF\ however the \type{cm} operator affects the +%D points as well as the pen (stroke). Like more \PDF\ +%D operators, \type{cm} is defined in a bit ambiguous way. +%D The only save route for non||circular penshapes, is saving +%D the path, recalculating the points and applying the +%D transformation matrix in such a way that we can be sure +%D that its behavior is well defined. This comes down to +%D inverting the path and applying \type{cm} to that path as +%D well as the pen. This all means that we have to save the +%D path. + +%D In \METAPOST\ there are three ways to handle a path $p$: +%D +%D \starttyping +%D draw p; fill p; filldraw p; +%D \stoptyping +%D +%D The last case outputs a \type{gsave fill grestore} before +%D \type{stroke}. Handling the path outside the main loops +%D saves about 40\% run time.\footnote{We can save some more by +%D following the \METAPOST\ output routine, but for the moment +%D we keep things simple.} Switching between the main loop and +%D the path loop is done by means of the recursely called +%D macro \type{\handleMPsequence}. + +\def\handleMPpath + {\chardef\finiMPpath0 + \let\closeMPpath\relax + \let\flushMPpath\flushnormalMPpath + \resetMPstack + \nofMPsegments\plusone + \let\handleMPsequence\dohandleMPpath + \dohandleMPpath} + +%D Most paths are drawn with simple round pens. Therefore we've +%D split up the routine in two. + +\def\flushnormalMPsegment + {\ifcase\getMPkeyword\relax + \PDFcode{\!MPgMPs1 \!MPgMPs2 l}% + \or + \PDFcode{\!MPgMPs1 \!MPgMPs2 \!MPgMPs3 \!MPgMPs4 \!MPgMPs5 \!MPgMPs6 c}% + \or + \PDFcode{\!MP\lastMPmoveX\space\!MP\lastMPmoveY\space l S}% + \or + \edef\lastMPmoveX{\gMPs1}% evt \!MP here + \edef\lastMPmoveY{\gMPs2}% + \PDFcode{\!MP\lastMPmoveX\space \!MP\lastMPmoveY\space m}% + \fi} + +\def\flushconcatMPsegment + {\ifcase\getMPkeyword\relax + \doMPconcat{\gMPs1}\a{\gMPs2}\b% + \PDFcode{\!MP\a\space\!MP\b\space l}% + \or + \doMPconcat{\gMPs1}\a{\gMPs2}\b% + \doMPconcat{\gMPs3}\c{\gMPs4}\d% + \doMPconcat{\gMPs5}\e{\gMPs6}\f% + \PDFcode{\!MP\a\space\!MP\b\space + \!MP\c\space\!MP\d\space + \!MP\e\space\!MP\f\space c}% + \or + \bgroup + \noMPtranslate + \doMPconcat\lastMPmoveX\a\lastMPmoveY\b% + \PDFcode{\!MP\a\space\!MP\b\space l S}% + \egroup + \or + \edef\lastMPmoveX{\gMPs1}% + \edef\lastMPmoveY{\gMPs2}% + \doMPconcat\lastMPmoveX\a\lastMPmoveY\b% + \PDFcode{\!MP\a\space\!MP\b\space m}% + \fi} + +\def\doflushsomeMPpath + {\dodoflushsomeMPpath + \advance\nofMPsegments \plusone + \ifnum\nofMPsegments<\scratchcounter + \expandafter\doflushsomeMPpath + \fi} + +\def\flushsomeMPpath + {\scratchcounter\nofMPsegments + \nofMPsegments\plusone + \doflushsomeMPpath} + +\def\flushnormalMPpath{\let\dodoflushsomeMPpath\flushnormalMPsegment\flushsomeMPpath} + +%OLD \def\flushconcatMPpath{\let\dodoflushsomeMPpath\flushconcatMPsegment\flushsomeMPpath} + +%NEW pre-calculate 1/D so it needn't be repeated for each control point. + +\def\flushconcatMPpath + {\MPreciprocaldeterminant + \let\dodoflushsomeMPpath\flushconcatMPsegment\flushsomeMPpath} + +%D The transformation of the coordinates is handled by one of +%D the macros Tanmoy posted to the \PDFTEX\ mailing list. +%D I rewrote and optimized the original macro to suit the other +%D macros in this module. +%D +%D \starttyping +%D \doMPconcat {x position} \xresult {y position} \yresult +%D \stoptyping +%D +%D By setting the auxiliary \DIMENSIONS\ \type{\dimen0} upto +%D \type{\dimen10} only once per path, we save over 20\% run +%D time. Some more speed was gained by removing some parameter +%D passing. These macros can be optimized a bit more by using +%D more constants. There is however not much need for further +%D optimization because penshapes usually are round and +%D therefore need no transformation. Nevertheless we move the +%D factor to the outer level and use a bit different \type{pt} +%D removal macro. Although the values represent base points, +%D we converted them to pure points, simply because those can +%D be converted back. + +%OLD \mathchardef\MPconcatfactor=256 % beware don't remove spaces before it + +%OLD \def\doMPreducedimen#1 +%OLD {\count0\MPconcatfactor +%OLD \advance\dimen#1 \ifdim\dimen#1>\zeropoint .5\else -.5\fi\count0 +%OLD \divide\dimen#1 \count0\relax} + +%OLD % too inaccurate (see old pragma logo) +%OLD +%OLD \def\doMPreducedimen#1 +%OLD {\count0=\MPconcatfactor +%OLD \divide\dimen#1 \count0\relax} + +%OLD \def\doMPreducedimen#1 +%OLD {\advance\dimen#1 \ifdim\dimen#1>\zeropoint .5\else -.5\fi\MPconcatfactor +%OLD \divide\dimen#1 \MPconcatfactor} + +%D The transformation code is rewritten by Daniel H. Luecking who +%D describes his patch as follows: +%D +%D We would like to divide 1 by $X$, but all divisions are integer so +%D for accuracy we want to convert to large integers and make sure the +%D integer quotient has as many significant digits as possible. Thus we +%D need to replace $1/X$ with $M/N$ where $N$ is as large as possible +%D and $M/N$ is as large as possible. Also for simplicity $M$ should be +%D a power of 2. So we make $M = 2^{30}$ \footnote{$2^{31} - 1$ is the +%D largest legal integer. Using it (and simply ignoring the inaccuracy +%D caused by $-1$) turns out to be at least as accurate in all cases, +%D and more accurate in some.} (largest legal power of 2) and adjust +%D $X$ downward (if necessary) to the the range $1-2^{16}$. This gives +%D at least 15 significant binary digits, (almost as accurate as +%D \METAPOST\ for numbers near 1) or almost 5 significant figures +%D (decimal). + +\newcount\MPscratchCnt +\newdimen\MPscratchDim % will be assigned global + +\def\MPadjustdimen % sets \MPscratchDim and \MPscratchCnt + {\MPscratchCnt\zerocount + \doMPadjustdimen} + +\def\doMPadjustdimen + {\ifdim\MPscratchDim>\onepoint + \divide\MPscratchDim 2 + \advance\MPscratchCnt \plusone + \expandafter\doMPadjustdimen + \fi} + +%OLD \def\doMPexpanddimen#1 +%OLD {\multiply\dimen#1 \MPconcatfactor\relax} + +%D DHL: When viewed as an integer, $1 \hbox{pt}=2^{16}$ so $2^{32}/X$ +%D is the right way to do $(1 \hbox{pt})/(X \hbox{pt})$ and get the +%D answer in points. But we are limited to $2^{30}/X$. However, we +%D actually do $[ 2^{30} / (X/2^K) ]*2^{2-K}$ where $K$ is the number +%D of halvings it takes to bring $X$ below $1 \hbox{pt}$. If $K$ is 0 +%D or 1 we readjust by multiplying by 4 or 2, otherwise by halving +%D $(K-2)$ times \type {\MPscratchCnt} holds the value of $K$ from +%D \type {\MPadjustdimen}. + +\def\MPreadjustdimen % acts on \MPscratchDim and MPscratchCnt + {\ifcase\MPscratchCnt + \multiply\scratchdimen 4 + \or + \multiply\scratchdimen 2 + \else + \expandafter\doMPreadjustdimen + \fi} + +\def\doMPreadjustdimen + {\ifnum\MPscratchCnt>2 + \divide\scratchdimen 2 + \advance\MPscratchCnt \minusone + \expandafter\doMPreadjustdimen + \fi} + +\def\MPreciprocaldeterminant + {\scratchdimen\withoutpt\the\dimen0 \dimen6 % s_x*s_y + \advance\scratchdimen - \withoutpt\the\dimen2 \dimen4 % s_x*s_y - r_x*r_y + \ifdim\scratchdimen<\zeropoint % we need a positive dimension + \scratchdimen-\scratchdimen % for \MPadjustdimen (?) + \doMPreciprocal + \scratchdimen-\scratchdimen + \else + \doMPreciprocal + \fi + \edef\MPreciprocal{\withoutpt\the\scratchdimen}} + +\newcount\MPnumerator \MPnumerator = 1073741824 % 2^{30} + +% todo: dimexpr + +\def\doMPreciprocal % replace \scratchdimen with its reciprocal + {\ifdim\scratchdimen=\onepoint \else + \MPadjustdimen + \scratchcounter\MPnumerator + \divide\scratchcounter\scratchdimen + \scratchdimen1\scratchcounter % 1 needed ! + \MPreadjustdimen + \fi} + +%OLD \def\presetMPconcat +%OLD {\dimen 0=\gMPs1\onepoint \doMPreducedimen 0 % r_x +%OLD \dimen 2=\gMPs2\onepoint \doMPreducedimen 2 % s_x +%OLD \dimen 4=\gMPs3\onepoint \doMPreducedimen 4 % s_y +%OLD \dimen 6=\gMPs4\onepoint \doMPreducedimen 6 % r_y +%OLD \dimen 8=\gMPs5\onepoint \doMPreducedimen 8 % t_x +%OLD \dimen10=\gMPs6\onepoint \doMPreducedimen10 } % t_y +%OLD +%OLD \def\presetMPscale +%OLD {\dimen 0=\gMPs1\onepoint \doMPreducedimen 0 +%OLD \dimen 2 \zeropoint +%OLD \dimen 4 \zeropoint +%OLD \dimen 6=\gMPs2\onepoint \doMPreducedimen 6 +%OLD \dimen 8 \zeropoint +%OLD \dimen10 \zeropoint} + +\def\cleanupMPconcat + {\ignoreMPspecials + \docleanupMPargument1% + \docleanupMPargument6% + \keepMPspecials} + +\def\presetMPconcat + {\dimen 0=\gMPs1\onepoint % s_x + \dimen 2=\gMPs2\onepoint % r_x + \dimen 4=\gMPs3\onepoint % r_y + \dimen 6=\gMPs4\onepoint % s_y + \dimen 8=\gMPs5\onepoint % t_x + \dimen10=\gMPs6\onepoint} % t_y + +\def\presetMPscale + {\dimen 0=\gMPs1\onepoint + \dimen 2 \zeropoint + \dimen 4 \zeropoint + \dimen 6=\gMPs2\onepoint + \dimen 8 \zeropoint + \dimen10 \zeropoint} + +\def\noMPtranslate % use this one grouped + {\dimen 8 \zeropoint % t_x + \dimen10 \zeropoint} % t_y + +%D \starttyping +%D \def\doMPconcat#1#2#3#4% +%D {\dimen12=#1 pt \doMPreducedimen12 % p_x +%D \dimen14=#3 pt \doMPreducedimen14 % p_y +%D % +%D \dimen16 \dimen 0 +%D \multiply \dimen16 \dimen 6 +%D \dimen20 \dimen 2 +%D \multiply \dimen20 \dimen 4 +%D \advance \dimen16 -\dimen20 +%D % +%D \dimen18 \dimen12 +%D \multiply \dimen18 \dimen 6 +%D \dimen20 \dimen14 +%D \multiply \dimen20 \dimen 4 +%D \advance \dimen18 -\dimen20 +%D \dimen20 \dimen 4 +%D \multiply \dimen20 \dimen10 +%D \advance \dimen18 \dimen20 +%D \dimen20 \dimen 6 +%D \multiply \dimen20 \dimen 8 +%D \advance \dimen18 -\dimen20 +%D % +%D \multiply \dimen12 -\dimen 2 +%D \multiply \dimen14 \dimen 0 +%D \advance \dimen12 \dimen14 +%D \dimen20 \dimen 2 +%D \multiply \dimen20 \dimen 8 +%D \advance \dimen12 \dimen20 +%D \dimen20 \dimen 0 +%D \multiply \dimen20 \dimen10 +%D \advance \dimen12 -\dimen20 +%D % +%D \doMPreducedimen16 +%D \divide \dimen18 \dimen16 \doMPexpanddimen18 +%D \divide \dimen12 \dimen16 \doMPexpanddimen12 +%D % +%D \edef#2{\withoutpt\the\dimen18}% % p_x^\prime +%D \edef#4{\withoutpt\the\dimen12}} % p_y^\prime +%D \stoptyping + +%D The following optimization resulted from some tests by +%D and email exchanges with Sanjoy Mahajan. +%D +%D \starttyping +%D \def\doMPconcat#1#2#3#4% +%D {\dimen12=#1 pt \doMPreducedimen12 % p_x +%D \dimen14=#3 pt \doMPreducedimen14 % p_y +%D % +%D \dimen16 \dimen 0 +%D \multiply \dimen16 \dimen 6 +%D \dimen20 \dimen 2 +%D \multiply \dimen20 \dimen 4 +%D \advance \dimen16 -\dimen20 +%D % +%D \dimen18 \dimen12 +%D \multiply \dimen18 \dimen 6 +%D \dimen20 \dimen14 +%D \multiply \dimen20 \dimen 4 +%D \advance \dimen18 -\dimen20 +%D \dimen20 \dimen 4 +%D \multiply \dimen20 \dimen10 +%D \advance \dimen18 \dimen20 +%D \dimen20 \dimen 6 +%D \multiply \dimen20 \dimen 8 +%D \advance \dimen18 -\dimen20 +%D % +%D \multiply \dimen12 -\dimen 2 +%D \multiply \dimen14 \dimen 0 +%D \advance \dimen12 \dimen14 +%D \dimen20 \dimen 2 +%D \multiply \dimen20 \dimen 8 +%D \advance \dimen12 \dimen20 +%D \dimen20 \dimen 0 +%D \multiply \dimen20 \dimen10 +%D \advance \dimen12 -\dimen20 +%D % +%D %\ifdim\dimen16>1pt % oeps, can be < 1pt too +%D \ifdim\dimen16=1pt \else +%D \ifdim\dimen16>\MPconcatfactor pt +%D \doMPreducedimen16 +%D \divide \dimen18 \dimen16 \doMPexpanddimen18 +%D \divide \dimen12 \dimen16 \doMPexpanddimen12 +%D \else +%D \divide \dimen18 \dimen16 \doMPexpanddimen18 \doMPexpanddimen18 +%D \divide \dimen12 \dimen16 \doMPexpanddimen12 \doMPexpanddimen12 +%D \fi +%D \fi +%D % +%D \edef#2{\withoutpt\the\dimen18}% % p_x^\prime +%D \edef#4{\withoutpt\the\dimen12}} % p_y^\prime +%D \stoptyping +%D +%D But, this one is still too inaccurate, so we now have: + +%D We cannot use \type {\beginETEX} here since in plain we +%D get \type {\outer} problems, sigh. + +%OLD \beginTEX +%OLD +%OLD \def\MPcriteriumA {512pt} % scale +%OLD \def\MPcriteriumB {2pt} % scale +%OLD +%OLD \endTEX +%OLD +%OLD \ifx\MPcriteriumA\undefined +%OLD +%OLD \newdimen\MPcriteriumA \MPcriteriumA=512pt +%OLD \newdimen\MPcriteriumB \MPcriteriumB= 2pt +%OLD +%OLD \fi + +%OLD \def\doMPconcat#1#2#3#4% +%OLD {\dimen12=#1pt % p_x +%OLD \dimen14=#3pt % p_y +%OLD % +%OLD \chardef\MPfactor\zerocount +%OLD \ifdim\dimen4<\MPcriteriumB\ifdim\dimen4>-\MPcriteriumB +%OLD \ifdim\dimen6<\MPcriteriumB\ifdim\dimen6>-\MPcriteriumB +%OLD \ifdim\dimen8<\MPcriteriumB\ifdim\dimen8>-\MPcriteriumB +%OLD \ifdim\dimen10<\MPcriteriumB\ifdim\dimen10>-\MPcriteriumB +%OLD \chardef\MPfactor\plusone +%OLD \fi\fi +%OLD \fi\fi +%OLD \fi\fi +%OLD \fi\fi +%OLD \ifcase\MPfactor % spurious 0 removed +%OLD \chardef\MPfactor\plusone +%OLD \ifdim\dimen12<\MPcriteriumA\ifdim\dimen12>-\MPcriteriumA +%OLD \ifdim\dimen14<\MPcriteriumA\ifdim\dimen14>-\MPcriteriumA +%OLD \chardef\MPfactor16 +%OLD \fi\fi +%OLD \fi\fi +%OLD \fi +%OLD % +%OLD \multiply\dimen12 \MPfactor +%OLD \multiply\dimen14 \MPfactor +%OLD % +%OLD \doMPreducedimen12 +%OLD \doMPreducedimen14 +%OLD % +%OLD \dimen16 \dimen 0 +%OLD \multiply \dimen16 \dimen 6 +%OLD \dimen20 \dimen 2 +%OLD \multiply \dimen20 \dimen 4 +%OLD \advance \dimen16 -\dimen20 +%OLD % +%OLD \dimen18 \dimen12 +%OLD \multiply \dimen18 \dimen 6 +%OLD \dimen20 \dimen14 +%OLD \multiply \dimen20 \dimen 4 +%OLD \advance \dimen18 -\dimen20 +%OLD \dimen20 \dimen 4 +%OLD \multiply \dimen20 \dimen10 +%OLD \advance \dimen18 \dimen20 +%OLD \dimen20 \dimen 6 +%OLD \multiply \dimen20 \dimen 8 +%OLD \advance \dimen18 -\dimen20 +%OLD % +%OLD \multiply \dimen12 -\dimen 2 +%OLD \multiply \dimen14 \dimen 0 +%OLD \advance \dimen12 \dimen14 +%OLD \dimen20 \dimen 2 +%OLD \multiply \dimen20 \dimen 8 +%OLD \advance \dimen12 \dimen20 +%OLD \dimen20 \dimen 0 +%OLD \multiply \dimen20 \dimen10 +%OLD \advance \dimen12 -\dimen20 +%OLD % +%OLD \ifdim\dimen16=\onepoint \else +%OLD \ifdim\dimen16>\MPconcatfactor \onepoint \relax +%OLD \doMPreducedimen16 +%OLD \divide \dimen18 \dimen16 \doMPexpanddimen18 +%OLD \divide \dimen12 \dimen16 \doMPexpanddimen12 +%OLD \else +%OLD \divide \dimen18 \dimen16 \doMPexpanddimen18 \doMPexpanddimen18 +%OLD \divide \dimen12 \dimen16 \doMPexpanddimen12 \doMPexpanddimen12 +%OLD \fi +%OLD \fi +%OLD % +%OLD \divide\dimen18 \MPfactor +%OLD \divide\dimen12 \MPfactor +%OLD % +%OLD \edef#2{\withoutpt\the\dimen18}% % p_x^\prime +%OLD \edef#4{\withoutpt\the\dimen12}} % p_y^\prime + +%D DHL: Ideally, $r_x$, $r_y$, $s_x$, $s_y$ should be in macros, not +%D dimensions (they are scalar quantities after all, not lengths). I +%D suppose the authors decided to do calculations with integer +%D arithmetic instead of using real factors because it's faster. +%D However, the actual macros test slower, possibly because I've +%D omitted three nested loops. In my test files, my approach is more +%D accurate. It is also far simpler and overflow does not seem to be a +%D significant concern. The scale factors written by Metapost are (?) +%D always $<=1$ (it scales coordinates internally) and coordinates are +%D always likely to be less than \type {\maxdimen}. +%D +%D If this should ever cause problems, the scale factors can be reduced. + +\def\doMPconcat#1#2#3#4% + {\dimen12=#1pt % p_x % #1\onepoint + \dimen14=#3pt % p_y % #3\onepoint + \advance\dimen12 -\dimen8 % p_x - t_x + \advance\dimen14 -\dimen10 % p_y - t_y + \dimen18=\withoutpt\the\dimen6 \dimen12 % s_y(p_x - t_x) + \advance\dimen18 -\withoutpt\the\dimen4 \dimen14 % - r_y(p_y-t_y) + \dimen14=\withoutpt\the\dimen0 \dimen14 % s_x(p_y-t_y) + \advance\dimen14 -\withoutpt\the\dimen2 \dimen12 % - r_x(p_x-t_x) + % \MPreciprocal contains precomputed 1/D: + \dimen18=\MPreciprocal\dimen18 + \dimen14=\MPreciprocal\dimen14 + \edef#2{\withoutpt\the\dimen18}% % p_x^\prime + \edef#4{\withoutpt\the\dimen14}} % p_y^\prime + +% faster but not that often used +% +% \def\doMPconcat#1#2#3#4% +% {\dimen12\dimexpr#1\points-\dimen 8\relax % p_x-t_x +% \dimen14\dimexpr#3\points-\dimen10\relax % p_y-t_y +% \dimen18\dimexpr\withoutpt\the\dimen6\dimen12-\withoutpt\the\dimen4\dimen14\relax % s_y(p_x-t_x)-r_y(p_y-t_y) +% \dimen14\dimexpr\withoutpt\the\dimen0\dimen14-\withoutpt\the\dimen2\dimen12\relax % s_x(p_y-t_y)-r_x(p_x-t_x) +% \edef#2{\withoutpt\the\dimexpr\MPreciprocal\dimen18\relax}% % p_x^\prime +% \edef#4{\withoutpt\the\dimexpr\MPreciprocal\dimen14\relax}} % p_y^\prime + +%D One reason for Daniel to write this patch was that at small sizes +%D the accuracy was less than optimal. Here is a test that demonstrates +%D that his alternative is pretty good: +%D +%D \startlinecorrection +%D \startMPcode +%D for i = 5cm,1cm,5mm,1mm,.5mm,.1mm,.01mm : +%D draw fullcircle scaled i withpen pencircle xscaled (i/10) yscaled (i/20) rotated 45 ; +%D endfor ; +%D \stopMPcode +%D \stoplinecorrection + +%D The following explanation of the conversion process was +%D posted to the \PDFTEX\ mailing list by Tanmoy. The original +%D macro was part of a set of macro's that included sinus and +%D cosinus calculations as well as scaling and translating. The +%D \METAPOST\ to \PDF\ conversion however only needs +%D transformation. + +%M \start \switchtobodyfont [ss] + +%D Given a point $(U_x, U_y)$ in user coordinates, the business +%D of \POSTSCRIPT\ is to convert it to device space. Let us say +%D that the device space coordinates are $(D_x, D_y)$. Then, in +%D \POSTSCRIPT\ $(D_x, D_y)$ can be written in terms of +%D $(U_x, U_y)$ in matrix notation, either as +%D +%D \placeformula +%D \startformula +%D \pmatrix{D_x&D_y&1\cr} = \pmatrix{U_x&U_y&1\cr} +%D \pmatrix{s_x&r_x&0\cr +%D r_y&s_y&0\cr +%D t_x&t_y&1\cr} +%D \stopformula +%D +%D or +%D +%D \placeformula +%D \startformula +%D \pmatrix{D_x\cr D_y\cr 1} = \pmatrix{s_x&r_y&t_x\cr +%D r_x&s_y&t_y\cr +%D 0 &0 &1 \cr} +%D \pmatrix{U_x\cr +%D U_y\cr +%D 1 \cr} +%D \stopformula +%D +%D both of which is a shorthand for the same set of equations: +%D +%D \placeformula +%D \startformula +%D D_x = s_x U_x + r_y U_y + t_x +%D \stopformula +%D +%D \placeformula +%D \startformula +%D D_y = r_x U_x + s_y U_y + t_y +%D \stopformula +%D +%D which define what is called an `affine transformation'. +%D +%D \POSTSCRIPT\ represents the `transformation matrix' as a +%D six element matrix instead of a $3\times 3$ array because +%D three of the elements are always~0, 0 and~1. Thus the above +%D transformation is written in postscript as $[s_x\, r_x\, +%D r_y\, s_y\, t_x\, t_y]$. However, when doing any +%D calculations, it is useful to go back to the original +%D matrix notation (whichever: I will use the second) and +%D continue from there. +%D +%D As an example, if the current transformation matrix is +%D $[s_x\, r_x\, r_y\, s_y\, t_x\, t_y]$ and you say \typ{[a b +%D c d e f] concat}, this means: +%D +%D \startnarrower +%D Take the user space coordinates and transform them to an +%D intermediate set of coordinates using array $[a\, b\, c\, d\, +%D e\, f]$ as the transformation matrix. +%D +%D Take the intermediate set of coordinates and change them to +%D device coordinates using array $[s_x\, r_x\, r_y\, s_y\, t_x\, t_y]$ +%D as the transformation matrix. +%D \stopnarrower +%D +%D Well, what is the net effect? In matrix notation, it is +%D +%D \placeformula +%D \startformula +%D \pmatrix{I_x\cr I_y\cr 1\cr} = \pmatrix{a&c&e\cr +%D b&d&f\cr +%D 0&0&1\cr} +%D \pmatrix{U_x\cr +%D U_y\cr +%D 1 \cr} +%D \stopformula +%D +%D \placeformula +%D \startformula +%D \pmatrix{D_y\cr D_y\cr 1\cr} = \pmatrix{s_x&r_y&t_x\cr +%D r_x&s_y&t_y\cr +%D 0 &0 &1 \cr} +%D \pmatrix{I_x\cr +%D I_y\cr +%D 1 \cr} +%D \stopformula +%D +%D where $(I_x, I_y)$ is the intermediate coordinate. +%D +%D Now, the beauty of the matrix notation is that when there is +%D a chain of such matrix equations, one can always compose +%D them into one matrix equation using the standard matrix +%D composition law. The composite matrix from two matrices can +%D be derived very easily: the element in the $i$\high{th} +%D horizontal row and $j$\high{th} vertical column is +%D calculated by`multiplying' the $i$\high{th} row of the first +%D matrix and the $j$\high{th} column of the second matrix (and +%D summing over the elements). Thus, in the above: +%D +%D \placeformula +%D \startformula +%D \pmatrix{D_x\cr D_y\cr 1} = \pmatrix{s_x^\prime&r_y^\prime&t_x^\prime\cr +%D r_x^\prime&s_y^\prime&t_y^\prime\cr +%D 0 &0 &0 \cr} +%D \pmatrix{U_x\cr +%D U_y\cr +%D 1 \cr} +%D \stopformula +%D +%D with +%D +%D \placeformula +%D \startformula +%D \eqalign +%D {s_x^\prime & = s_x a + r_y b \cr +%D r_x^\prime & = r_x a + s_y b \cr +%D r_y^\prime & = s_x c + r_y d \cr +%D s_y^\prime & = r_x c + s_y d \cr +%D t_x^\prime & = s_x e + r_y f + t_x \cr +%D t_y^\prime & = r_x e + s_y f + t_y \cr} +%D \stopformula + +%D In fact, the same rule is true not only when one is going +%D from user coordinates to device coordinates, but whenever +%D one is composing two `transformations' together +%D (transformations are `associative'). Note that the formula +%D is not symmetric: you have to keep track of which +%D transformation existed before (i.e.\ the equivalent of +%D $[s_x\, r_x\, r_y\, s_y\, t_x\, t_y]$) and which was +%D specified later (i.e.\ the equivalent of $[a\, b\, c\, d\, +%D e\, f]$). Note also that the language can be rather +%D confusing: the one specified later `acts earlier', +%D converting the user space coordinates to intermediate +%D coordinates, which are then acted upon by the pre||existing +%D transformation. The important point is that order of +%D transformation matrices cannot be flipped (transformations +%D are not `commutative'). +%D +%D Now what does it mean to move a transformation matrix +%D before a drawing? What it means is that given a point +%D $(P_x, P_y)$ we need a different set of coordinates +%D $(P_x^\prime, P_y^\prime)$ such that if the transformation +%D acts on $(P_x^\prime, P_y^\prime)$, they produce $(P_x, +%D P_y)$. That is we need to solve the set of equations: +%D +%D \placeformula +%D \startformula +%D \pmatrix{P_x\cr P_y\cr 1\cr} = \pmatrix{s_x&r_y&t_x\cr +%D r_x&s_y&t_y\cr +%D 0 &0 &1 \cr} +%D \pmatrix{P_x^\prime\cr +%D P_y^\prime\cr +%D 1 \cr} +%D \stopformula +%D +%D Again matrix notation comes in handy (i.e. someone has +%D already solved the problem for us): we need the inverse +%D transformation matrix. The inverse transformation matrix can +%D be calculated very easily: +%D +%D \placeformula +%D \startformula +%D \pmatrix{P_x^\prime\cr P_y^\prime\cr 1\cr} = +%D \pmatrix{s_x^\prime&r_y^\prime&t_x^\prime\cr +%D r_x^\prime&s_y^\prime&t_y^\prime\cr +%D 0 &0 &1 \cr} +%D \pmatrix{P_x\cr +%D P_y\cr +%D 1 \cr} +%D \stopformula +%D +%D where, the inverse transformation matrix is given by +%D +%D \placeformula +%D \startformula +%D \eqalign +%D {D & = s_x s_y - r_x r_y \cr +%D s_x^\prime & = s_y / D \cr +%D s_y^\prime & = s_x / D \cr +%D r_x^\prime & = - r_x / D \cr +%D r_y^\prime & = - r_y / D \cr +%D t_x^\prime & = ( - s_y t_x + r_y t_y ) / D \cr +%D t_y^\prime & = ( r_x t_x - s_x t_y ) / D \cr} +%D \stopformula +%D +%D And you can see that when expanded out, this does +%D give the formulas: +%D +%D \placeformula +%D \startformula +%D P_x^\prime = { { s_y(p_x-t_x) + r_y(t_y-p_y) } \over +%D { s_x s_y-r_x r_y } } +%D \stopformula +%D +%D \placeformula +%D \startformula +%D P_y^\prime = { { s_x(p_y-t_y) + r_x(t_x-p_x) } \over +%D { s_x*s_y-r_x*r_y } } +%D \stopformula +%D +%D The code works by representing a real number by converting +%D it to a dimension to be put into a \DIMENSION\ register: 2.3 would +%D be represented as 2.3pt for example. In this scheme, +%D multiplying two numbers involves multiplying the \DIMENSION\ +%D registers and dividing by 65536. Accuracy demands that the +%D division be done as late as possible, but overflow +%D considerations need early division. +%D +%D Division involves dividing the two \DIMENSION\ registers and +%D multiplying the result by 65536. Again, accuracy would +%D demand that the numerator be multiplied (and|/|or the +%D denominator divided) early: but that can lead to overflow +%D which needs to be avoided. +%D +%D If nothing is known about the numbers to start with (in +%D concat), I have chosen to divide the 65536 as a 256 in each +%D operand. However, in the series calculating the sine and +%D cosine, I know that the terms are small (because I never +%D have an angle greater than 45 degrees), so I chose to +%D apportion the factor in a different way. + +%M \stop + +%D The path is output using the values saved on the stack. If +%D needed, all coordinates are recalculated. + +\def\finishMPpath + {\PDFcode{\ifcase\finiMPpath W n\or S\or f\or B\fi}} + +\def\processMPpath + {\checkMPpath + \ifcase\nofMPsegments\else + \flushMPpath + \closeMPpath + \finishMPpath + \fi + \let\handleMPsequence\dohandleMPsequence + \resetMPstack + \nofMPsegments\zerocount + \handleMPsequence} + +%D The following \METAPOST\ code is quite valid but, when +%D processed and converted to \PDF, will make a file +%D unprintable on a Hewlett Packard printer (from Acrobat +%D $v<=5$). Who is to blame, the driver of the OS layer in +%D between, is hard to determine, so we add an additional +%D check. +%D +%D \starttyping +%D clip currentpicture to origin -- cycle ; +%D setbounds currentpicture to fullsquare scaled 5cm ; +%D \stoptyping + +\def\checkMPpath + {\ifcase\finiMPpath + \ifnum\nofMPsegments<3 % n is one ahead + \message{omitting zero clip path}% + \nofMPsegments\zerocount + \fi + \fi} + +%D In \PDF\ the \type{cm} operator must precede the path +%D specification. We therefore can output the \type{cm} at +%D the moment we encounter it. + +\def\handleMPpathconcat + {\presetMPconcat + \PDFcode{\gMPs1 \gMPs2 \gMPs3 \gMPs4 \gMPs5 \gMPs6 cm}% + \resetMPstack} + +\def\handleMPpathscale + {\presetMPscale + \PDFcode{\gMPs1 0 0 \gMPs2 0 0 cm}% + \resetMPstack} + +%D This macro interprets the path and saves it as compact as +%D possible. + +\def\dohandleMPpath#1% + {\ifcase\lccode`#1\relax + \@EA\dohandleMPpathA + \else + \@EA\dohandleMPpathB + \fi#1} + +\let\dohandleMPpathA\setMPsequence + +\def\dohandleMPpathB#1 % + {\def\somestring{#1}% + \ifx\somestring\PSlineto + \setMPkeyword0 + \else\ifx\somestring\PScurveto + \setMPkeyword1 + \else\ifx\somestring\PSrlineto + \setMPkeyword2 + \else\ifx\somestring\PSmoveto + \setMPkeyword3 + \else\ifx\somestring\PSclip + % \chardef\finiMPpath0 % already + \let\handleMPsequence\processMPpath + \else\ifx\somestring\PSgsave + \chardef\finiMPpath3 + \else\ifx\somestring\PSgrestore + \else\ifx\somestring\PSfill + \ifcase\finiMPpath + \chardef\finiMPpath2 + \let\handleMPsequence\processMPpath + \fi + \else\ifx\somestring\PSstroke + \ifcase\finiMPpath + \chardef\finiMPpath1 + \fi + \let\handleMPsequence\processMPpath + \else\ifx\somestring\PSclosepath + \def\closeMPpath{\PDFcode{h}}% + \else\ifx\somestring\PSconcat + \cleanupMPconcat + \let\flushMPpath\flushconcatMPpath + \handleMPpathconcat + \else\ifx\somestring\PSscale + \let\flushMPpath\flushconcatMPpath + \handleMPpathscale + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \handleMPsequence} + +%D The main conversion command is: +%D +%D \starttyping +%D \convertMPtoPDF {filename} {x scale} {y scale} +%D \stoptyping +%D +%D The dimensions are derived from the bounding box. So we +%D only have to say: +%D +%D \starttyping +%D \convertMPtoPDF{mp-pra-1.eps}{1}{1} +%D \convertMPtoPDF{mp-pra-1.eps}{.5}{.5} +%D \stoptyping + +%D \macros +%D {makeMPintoPDFobject,lastPDFMPobject} +%D +%D For experts there are a few more options. When attributes +%D are to be added, the code must be embedded in an object +%D accompanied with the appropriate directives. One can +%D influence this process with \type {\makeMPintoPDFobject}. +%D +%D This option defaults to~0, because \CONTEXT\ takes care +%D of objects at another level, which saves some bytes. +%D +%D \starttabulate[|l|l|p|] +%D \NC 0 \NC never \NC don't use an object \NC\NR +%D \NC 1 \NC always \NC always use an object \NC\NR +%D \NC 2 \NC optional \NC use object when needed \NC\NR +%D \stoptabulate +%D +%D The last object number used is avaliable in the macro +%D \type {\lastPDFMPobject}. + +\ifx\makeMPintoPDFobject\undefined \chardef\makeMPintoPDFobject=0 \fi + +\def\lastPDFMPobject{0} + +%D The additional code needed can be made available in the +%D (global) macro \type {\currentPDFresources}. + +\let\currentPDFresources\empty + +\newtoks\everyMPtoPDFconversion + +\def\convertMPtoPDF % #1#2#3% + {\bgroup + \ifx\pdfdecimaldigits\undefined\else \pdfdecimaldigits=5 \fi % new + \setbox\scratchbox\vbox\bgroup + \xdef\MPheight{\zeropoint}% + \xdef\MPwidth {\zeropoint}% + \forgetall + \offinterlineskip + \startMPresources + \doprocessMPtoPDFfile} % + +%D The next one is kind of private and probably will become obsolete): + +\def\processMPtoPDFfile % file xscale yscale + {\bgroup + \let\finishMPgraphic\egroup + \doprocessMPtoPDFfile} + +\let\setMPextensions\relax + +\def\doprocessMPtoPDFfile#1#2#3% file xscale yscale + {% the following line is needed for latex where onepoint is not + % onepoint but a number (maxdimen); some day i'll make a latex + % variant of this file so that i no longer have to deal with such + % issues; then i'll also speed up this module using a few context + % tricks + % + \let\onepoint\onerealpoint + % + \setMPspecials + \setMPextensions + \the\everyMPtoPDFconversion + \catcode`\^^M=\@@endofline + \startMPscanning + \let\do\empty + \xdef\MPxscale{#2}% + \xdef\MPyscale{#3}% + \xdef\MPxoffset{0}% + \xdef\MPyoffset{0}% + \xdef\MPyshift{\zeropoint}% + \donefalse + \let\handleMPsequence\dohandleMPsequence + \message{[MP to PDF]}% was: [MP to PDF #1] but there is a (#1) anyway + \input#1\relax} + +% strange rounding/clip in pdftex/viewer +% +% \def\finishMPgraphic +% {\stopMPresources +% \egroup +% \ifx\pdftexversion\undefined\else\ifnum\pdftexversion<14 % for the moment +% \chardef\makeMPintoPDFobject=0 +% \fi\fi +% \ifcase\makeMPintoPDFobject\or\or\ifx\currentPDFresources\empty\else +% \chardef\makeMPintoPDFobject=1 +% \fi\fi +% \setbox\scratchbox=\vbox +% {\forgetall +% \hbox +% {\PDFcode{q \MPxscale\space 0 0 \MPyscale\space \MPxoffset\space \MPyoffset\space cm}% +% \lower\MPyshift\box\scratchbox % unscaled shift +% \PDFcode{Q}}}% +% \ht\scratchbox\MPheight +% \wd\scratchbox\MPwidth +% \dp\scratchbox\zeropoint +% \ifcase\makeMPintoPDFobject +% \box\scratchbox +% \or +% \immediate\pdfxform resources{\currentPDFresources}\scratchbox +% \xdef\lastPDFMPobject{\the\pdflastxform}% +% \pdfrefxform\lastPDFMPobject +% \global\let\currentPDFresources\empty +% \else +% \box\scratchbox +% \fi +% \egroup} +% +% funny clip in viewer +% +% \setbox\scratchbox=\vbox +% {\forgetall +% \dimen0=\MPllx bp +% \dimen2=\MPlly bp +% \setbox\scratchbox=\hbox{\hskip-\dimen0\raise-\dimen2\box\scratchbox}% +% \ht\scratchbox=\zeropoint +% \dp\scratchbox=\zeropoint +% \wd\scratchbox=\zeropoint +% \hbox +% {\PDFcode{q \MPxscale\space 0 0 \MPyscale\space 0 0 cm}% +% \lower\MPshift\box\scratchbox +% \PDFcode{Q}}}% + +% \let\PDFMPformoffset\zeropoint + +\def\PDFMPformoffset + {\ifx\objectoffset\undefined\zeropoint\else\objectoffset\fi} + +\def\finishMPgraphic + {\stopMPresources + \egroup + \setbox\scratchbox\vbox + {\forgetall + \hbox + {\PDFcode{q \MPxscale\space 0 0 \MPyscale\space \MPxoffset\space \MPyoffset\space cm}% + \lower\MPyshift\box\scratchbox % unscaled shift + \PDFcode{Q}}}% + \ht\scratchbox\MPheight + \wd\scratchbox\MPwidth + \dp\scratchbox\zeropoint\relax + \dopackageMPgraphic\scratchbox + \egroup + \endinput} + +%D Alternative for \PDFTEX. We cannot come up with something more contexy +%D because this module is also used in \LATEX. + +\def\dopackageMPgraphic#1% #1 = boxregister + {%\ifx\pdfxform\undefined + % \chardef\makeMPintoPDFobject\zerocount % no pdftex at all + %\else\ifx\pdftexversion\undefined + % \chardef\makeMPintoPDFobject\zerocount % no pdftex at all + %\else\ifnum\pdftexversion<14 + % \chardef\makeMPintoPDFobject\zerocount % no resource support + %\else + % % keep the default value + %\fi\fi\fi + \ifcase\makeMPintoPDFobject\or\or\ifx\currentPDFresources\empty\else + % an existing value of 2 signals object support (set elsewhere) + \chardef\makeMPintoPDFobject\plusone + \fi\fi + \ifcase\makeMPintoPDFobject + \box#1% + \or + \scratchdimen\PDFMPformoffset\relax + \ifdim\scratchdimen>\zeropoint % compensate for error + \setbox#1\vbox spread 2\scratchdimen + {\forgetall\vss\hbox spread 2\scratchdimen{\hss\box#1\hss}\vss}% + \fi + \setMPPDFobject{\currentPDFresources}{#1}% + \ifdim\scratchdimen>\zeropoint % compensate for error + \vbox to \MPheight + {\forgetall\vss\hbox to \MPwidth{\hss\getMPPDFobject\hss}\vss}% + \else + \getMPPDFobject + \fi + \global\let\currentPDFresources\empty + \else + \box#1% + \fi} + +\def\setMPPDFobject#1#2% resources boxnumber + {\ifx\pdfxform\undefined + \def\getMPPDFobject{\box#2}% + \else\ifx\pdftexversion\undefined + \def\getMPPDFobject{\box#2}% + \else\ifnum\pdftexversion<14 + \def\getMPPDFobject{\box#2}% + \else + \ifx\everyPDFxform\undefined\else\the\everyPDFxform\fi + \immediate\pdfxform resources{#1}#2% + \edef\getMPPDFobject{\noexpand\pdfrefxform\the\pdflastxform}% + \fi\fi\fi} + +\let\getMPPDFobject\relax + +%D \macros +%D {deleteMPgraphic, +%D startMPresources, +%D stopMPresources} +%D +%D Here are a few hooks for \CONTEXT\ specific things. + +\ifx\deleteMPgraphic\undefined + \def\deleteMPgraphic#1{} +\fi + +\ifx\startMPresources\undefined + \let\startMPresources\relax + \let\stopMPresources\relax +\fi + +%D \macros +%D {twodigitMPoutput} +%D +%D We can limit the precision to two digits after the comma +%D by saying: +%D +%D \starttyping +%D \twodigitMPoutput +%D \stoptyping +%D +%D This option only works in \CONTEXT\ combined with \ETEX. + +\def\twodigitMPoutput + {\let\!MP \twodigitrounding + \def\!MPgMPs##1{\twodigitrounding{\gMPs##1}}% + \def\!MPgMPa##1{\twodigitrounding{\gMPa##1}}} + +\let\!MP \empty +\let\!MPgMPa\gMPa +\let\!MPgMPs\gMPs + +%D This kind of conversion is possible because \METAPOST\ +%D does all the calculations. Converting other \POSTSCRIPT\ +%D files would drive both me and \TEX\ crazy. + +\ifx\undefined\StopLatexHack \else \StopLatexHack \fi + +\protect % \endinput + +%D \module +%D [ file=supp-mpe, +%D version=1999.07.10, +%D title=\CONTEXT\ Support Macros, +%D subtitle=METAPOST Special Extensions, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +% fuzzy and complicating is the fact that we need to support +% context as well as mptopdf, so we cannot fall back on the +% special drivers and color module (although there may be +% good reasons to use a smaller context instead); also, +% shading is handled here while it should move to the special +% driver - to do! + +%D This module is still experimental and deals with some +%D extensions to \METAPOST. When using \POSTSCRIPT\ output, +%D these extensions can be supplied by means of proper +%D preamble definitions, but when producing \PDF\ we have to +%D set up the appropriate datastructures ourselves. It acts as +%D a plug in into \type {supp-pdf}. As soon as we need more +%D extensions, we will generalize these macro. Some +%D definitions will move to the special drivers. + +%D For usage in plain \TEX, say something: +%D +%D \starttyping +%D \input supp-pdf +%D \input supp-mpe +%D +%D \MPcmykcolorstrue +%D \MPspotcolorstrue +%D \chardef\makeMPintoPDFobject\plusone +%D \stoptyping + +\writestatus{loading}{MetaPost Special Extensions} + +%D We implement extensions by using the \METAPOST\ special +%D mechanism. Opposite to \TEX's specials, the \METAPOST\ ones +%D are flushed before or after the graphic data, but thereby +%D are no longer connected to a position. +%D +%D We implement specials by overloading the \type {fill} +%D operator. By counting the fills, we can let the converter +%D treat the appropriate fill in a special way. The +%D specification of the speciality can have two forms, +%D determined by the setting of a boolean variable: +%D +%D \starttyping +%D _inline_specials_ := false ; % comment like code (default) +%D _inline_specials_ := true ; % command like code +%D \stoptyping +%D +%D When the specification is embedded as comment, it looks +%D like: +%D +%D \starttyping +%D %%MetaPostSpecial <size> <data> <number> <identifier> +%D \stoptyping +%D +%D The in||line alternative is more tuned for \POSTSCRIPT, +%D since it permits us to define a macro \type {special}. +%D +%D \starttyping +%D inline : <data> <number> <identifier> <size> special +%D \stoptyping +%D +%D The \type {identifier} determines what to do, and the data +%D can be used to accomplish this. A type~2 shading function +%D has identifier~2. Alltogether, the number of parameters is +%D specified in \type {size}. The \type {number} is the number +%D of the fill that needs the special treatment. For a type~2 +%D and~3 shaded fill, the datablock contains the following + +%D data: +%D +%D \starttyping +%D from to n inner_r g b x y outer_r g b x y +%D from to n inner_r g b x y radius outer_r g b x y radius +%D \stoptyping +%D +%D The implementation below saves the data on the stack in +%D a way similar to the macros in \type {supp-pdf.tex}, and +%D just overload a few already defined handlers. That way, +%D the existing macros are still generic. \footnote {Actually, +%D the macros here are just as generic.} +%D +%D Currently the only extension concerns shading, which is +%D accomplished by handling yet another value of \type +%D {\finiMPpath}. The recource disctionary is stored and +%D later picked up by the general \CONTEXT\ figure inclusion +%D macros. + +\unprotect + +%D The \type {%%MetaPostSpecials: version.revision signal} line +%D triggers this module into handling color specifications kind +%D of special. We need this safeguard for non||special +%D usage. + +\chardef\MPspecialversion = 0 % specials when >1 +\chardef\MPspecialrevision = 0 % specials when >1 +\chardef\MPspecialsignal = 0 % passed on by graphic + +\chardef\inlineMPspecials = 1 % only needed for stack resetting + +%D This macro handles the special definitions that are +%D passed as comment. + +\def\dohandleMPspecialcomment#1 + {\setMPargument{#1}% + \advance\scratchcounter \minusone + \ifcase\scratchcounter + \handleMPspecialcommand + \donetrue + \doresetMPstack + \let\handleMPsequence\dohandleMPsequence + \expandafter\handleMPsequence + \else + \expandafter\dohandleMPspecialcomment + \fi} + +\def\handleMPspecialcomment #1 % number of arguments + {\doresetMPstack + \scratchcounter#1\relax + \ifcase\scratchcounter % when zero, inline shading is used + \chardef\inlineMPspecials\plusone + \let\handleMPsequence\dohandleMPsequence + \expandafter\handleMPsequence + \else + \chardef\inlineMPspecials\zerocount + \expandafter\dohandleMPspecialcomment + \fi} + +%D When defined inline, we use another macro to handle the +%D definitions. Actually, this macro is called by the +%D previous ones. + +\def\handleMPspecialcommand + {\ifcase\inlineMPspecials\or + \advance\nofMParguments \minusone % pop the size + \fi + \ifundefined\MPspecial + \message{[unknown \MPspecial]}% + \else + \csname\MPspecial\endcsname + \fi + \ifcase\inlineMPspecials + \doresetMPstack % 0 + \else + \resetMPstack % 1 + \fi} + +%D This macro triggers special support. Currently, the +%D version and revision number are not used. Any version number +%D greater than zero will enable special support. + +\newconditional\manyMPspecials % \settrue\manyMPspecials + +\def\handleMPspecialscomment #1.#2 #3 % version.revision signal #4=div=1000|10000 + {\doresetMPstack + \chardef\MPspecialversion #1% + \chardef\MPspecialrevision#2% + \chardef\MPspecialsignal #3% + \let\handleMPsequence\dohandleMPsequence + \ifnum#1=\plusone + \expandafter\handleMPsequence + \else + \expandafter\handleMPspecialscommentx + \fi} + +\def\handleMPspecialscommentx #1 % version 2 +% {\doifelsedoifelse{#1}{10000}{\settrue\manyMPspecials}{\setfalse\manyMPspecials}% local + {\ifnum10000=0#1\relax\settrue\manyMPspecials\else\setfalse\manyMPspecials\fi + \handleMPsequence} + +% one can say (in meta-ini): +% +% \prependtoks +% _special_div_ := 1000\ifconditional\manyMPspecials0\fi ; +% \to \MPextensions + +%D In case of \PDF, we need to prepare resourcs. + +\newtoks\MPstartresources +\newtoks\MPstopresources + +\def\startMPresources + {\the\MPstartresources + \ifx\currentPDFresources\empty\else + \message{[unused resources]}% + \fi + \global\let\currentPDFresources\empty} + +\def\stopMPresources + {\let\currentPDFresources\empty + \the\MPstopresources} + +%D Since colors are not subjected to transformations, we can +%D only use colors as signal. In our case, we use a dummy colored +%D path with a red color component of \type {0.n}, so \type +%D {0.001} is the first path and \type {0.010} the tenth. Since +%D \METAPOST strips trailing zeros, we have to padd the string. + +\newif\ifMPcmykcolors +\newif\ifMPspotcolors + +\ifx\normalhandleMPrgbcolor\undefined % in case we reload this module + + \let\normalhandleMPrgbcolor \handleMPrgbcolor + \let\normalhandleMPcmykcolor\handleMPcmykcolor + \let\normalhandleMPgraycolor\handleMPgraycolor + \let\normalhandleMPspotcolor\handleMPspotcolor + +\fi + +%D When we are using \CONTEXT, we will fall back to the +%D better color conversion routines. This also has the advantage +%D that we don't have to parse and convert the file. In this +%D alternative, \type {\!MP} is not (yet) supported. Because +%D we can (for efficiency reasons) turn off strokecolor, +%D something we cannot do in \METAPOST\ converted code. + +\newif\ifPDFMPstrokecolor \PDFMPstrokecolortrue + +%D [This code should move to meta-ini.] + +\ifCONTEXT % we can use this for a better xgstate handling + + \def\checkPDFMPstrokecolor + {\ifPDFMPstrokecolor \PDFstrokecolortrue \fi} + + \def\normalhandleMPrgbcolor + {{\checkPDFMPstrokecolor\execcolorR\gMPa1:\gMPa2:\gMPa3:0:0\od}} + + \def\normalhandleMPcmykcolor + {{\checkPDFMPstrokecolor\execcolorC\gMPa1:\gMPa2:\gMPa3:\gMPa4:0:0\od}} + + \def\normalhandleMPgraycolor + {{\checkPDFMPstrokecolor\execcolorS\gMPa1:0:0\od}} + + \def\normalhandleMPspotcolor % ??? + {{\checkPDFMPstrokecolor\execcolorP\gMPa1:\gMPa2:\gMPa3:\gMPa4:0:0\od}} + +\fi + +% In the previous macros we use the special drivers. A more +% direct approach would have been: +% +% \def\doPDFstartrgbcolormode#1#2#3% +% {\PDFcode{#1 #2 #3 rg #1 #2 #3 RG}} +% +% \def\doPDFstartcmykcolormode#1#2#3#4% +% {\PDFcode{#1 #2 #3 #4 k #1 #2 #3 #4 K}} +% +% \def\doPDFstartgraycolormode#1% +% {\PDFcode{#1 g #1 G}} +% +% \appendtoks +% \let\dostartrgbcolormode \doPDFstartrgbcolormode +% \let\dostartcmykcolormode\doPDFstartcmykcolormode +% \let\dostartgraycolormode\doPDFstartgraycolormode +% \to \everyMPtoPDFconversion + +%D Now we can handle special color signals. We only do this +%D when special are detected. + +% \def\MPrgbnumber#1{\expandafter\doMPrgbnumber#1000.0000\relax} +% \def\doMPrgbnumber#1.#2#3#4#5\relax{#2#3#4} + +%D We cannot use \type {\everyMPtoPDFconversion} because in \MPTOPDF\ +%D we don't have the \type {\appendtoks} macro available. + +\def\setMPextensions + {\ifconditional\manyMPspecials + \def\MPrgbnumber##1{\expandafter\doMPrgbnumber##10000.00000\relax}% + \def\doMPrgbnumber##1.##2##3##4##5##6\relax{##2##3##4##5}% + \else + \def\MPrgbnumber##1{\expandafter\doMPrgbnumber##1000.0000\relax}% + \def\doMPrgbnumber##1.##2##3##4##5\relax{##2##3##4}% + \fi} + +%D The naive case looks like: +%D +%D \starttyping +%D \def\handleMPrgbcolor% +%D {\setMPcolor +%D \ifcase\MPspecialversion +%D \resetMPcolor\normalhandleMPrgbcolor +%D \else\ifnum\MPrgbnumber\lastMPrvalue=\MPspecialsignal +%D % consider it to be a signal +%D \else +%D \resetMPcolor\normalhandleMPrgbcolor +%D \fi\fi} +%D \stoptyping +%D +%D However, since we want \CMYK\ support, we will use the +%D following implementation: + +% \def\setMPcolor +% {\edef\lastMPrvalue{\gMPa1}% +% \edef\lastMPgvalue{\gMPa2}% +% \edef\lastMPbvalue{\gMPa3}} +% +% speed up (hardly called, so no let is needed) + +\def\setMPcolor + {\edef\lastMPrvalue{\csname\@@MP01\endcsname}% + \edef\lastMPgvalue{\csname\@@MP02\endcsname}% + \edef\lastMPbvalue{\csname\@@MP03\endcsname}} + +\def\zeroMPrgbvalue{0.0} + +\def\resetMPcolor + {\let\lastMPrvalue\zeroMPrgbvalue + \let\lastMPgvalue\zeroMPrgbvalue + \let\lastMPbvalue\zeroMPrgbvalue} + +\resetMPcolor + +\def\@@MPSK{@MPSK@} +\def\@@MPSP{@MPSP@} + +\def\interceptMPcmykcolor % todo : \ifMPcmykcolors + {\ifcase\MPrgbnumber\lastMPgvalue + % cannot happen + \or + % 1 == cmyk color spec + \ifMPcmykcolors \dointerceptMPcmykcolor \fi + \or + % 2 == spot color + \ifMPspotcolors \dointerceptMPspotcolor \fi + \or + % 3 == rgb transparency + \invokeMPtransparencyspecial + \or + % 4 == cmyk transparency + \ifMPcmykcolors \invokeMPtransparencyspecial \fi + \or + % 5 == spot transparency + \ifMPspotcolors \invokeMPtransparencyspecial \fi + \else + % \writestatus{MPtoPDF}{unknown direct special}% + \fi} + +% ifcsname + +\def\dointerceptMPcmykcolor + {\revokeMPtransparencyspecial + \@EA\ifx\csname\@@MPSK\number\MPrgbnumber\lastMPbvalue\endcsname\relax\else + \@EA\@EA\@EA\setMPcmyk\csname\@@MPSK\number\MPrgbnumber\lastMPbvalue\endcsname + \normalhandleMPcmykcolor + \fi} + +\def\dointerceptMPspotcolor + {\revokeMPtransparencyspecial + \@EA\ifx\csname\@@MPSP\number\MPrgbnumber\lastMPbvalue\endcsname\relax\else + \@EA\@EA\@EA\setMPspot\csname\@@MPSP\number\MPrgbnumber\lastMPbvalue\endcsname + \normalhandleMPspotcolor + \fi} + +\def\handleMPrgbcolor + {\resetMPcolor + \ifcase\MPspecialversion + \normalhandleMPrgbcolor + \else + \setMPcolor + \ifnum\MPrgbnumber\lastMPrvalue=\MPspecialsignal\relax + \interceptMPcmykcolor + \else + \revokeMPtransparencyspecial + \normalhandleMPrgbcolor + \fi + \fi} + +\def\handleMPgraycolor + {\resetMPcolor + \ifcase\MPspecialversion \else \revokeMPtransparencyspecial \fi + \normalhandleMPgraycolor} + +\def\handleMPcmykcolor + {\resetMPcolor + \ifcase\MPspecialversion \else \revokeMPtransparencyspecial \fi + \normalhandleMPcmykcolor} + +%D Specials are define and recalled using: + +\def\MPspecial + {MP special \gMPs\nofMParguments} + +\def\defineMPspecial#1#2% + {\setvalue{MP special #1}{#2}} + +%D The path processing macro is slightly extended. + +\newtoks \invokeMPspecials + +\def\finishMPpath + {\PDFcode + {\ifcase\finiMPpath W n\or S\or f\or B\else W n\fi + \extraMPpathcode}} + +\def\processMPpath + {\checkMPpath % ! + \ifcase\nofMPsegments\else + \let\extraMPpathcode\empty + \ifcase\MPspecialversion\else + \ifnum\MPrgbnumber\lastMPrvalue=\MPspecialsignal + \ifnum\MPrgbnumber\lastMPgvalue>10 % really needed + \scratchcounter\MPrgbnumber\lastMPbvalue + \edef\currentMPspecial{\the\scratchcounter}% + \ifnum\finiMPpath=2 % to outer level + \the\invokeMPspecials + \fi + \fi + \fi + \fi + \flushMPpath + \closeMPpath + \finishMPpath + \fi + \let\handleMPsequence\dohandleMPsequence + \resetMPstack + \nofMPsegments0 + \handleMPsequence} + +%D Shading is an example of a more advanced graphic feature, +%D but users will seldom encounter those complications. Here +%D we only show a few simple examples, but many other +%D alternatives are possible by setting up the functions built +%D in \PDF\ in the appropriate way. +%D +%D Shading has to do with interpolation between two or more +%D points or user supplied ranges. In \PDF, the specifications +%D of a shade has to be encapsulated in objects and passed on +%D as resources. This is a \PDF\ level 1.3. feature. One can +%D simulate three dimensional shades as well and define simple +%D functions using a limited set of \POSTSCRIPT\ primitives. +%D Given the power of \METAPOST\ and these \PDF\ features, we +%D can achieve superb graphic effects. +%D +%D Since everything is hidden in \TEX\ and \METAPOST\ graphics, +%D we can stick to high level \CONTEXT\ command, as shown in +%D the following exmples. +%D +%D \startbuffer +%D \startuniqueMPgraphic{CircularShade} +%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ; +%D circular_shade(p,0,.2red,.9red) ; +%D \stopuniqueMPgraphic +%D +%D \startuniqueMPgraphic{LinearShade} +%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ; +%D linear_shade(p,0,.2blue,.9blue) ; +%D \stopuniqueMPgraphic +%D +%D \startuniqueMPgraphic{DuotoneShade} +%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ; +%D linear_shade(p,2,.5green,.5red) ; +%D \stopuniqueMPgraphic +%D \stopbuffer +%D +%D \typebuffer +%D +%D \getbuffer +%D +%D These graphics can be hooked into the overlay mechanism, +%D which is available in many commands. +%D +%D \startbuffer +%D \defineoverlay[demo 1][\uniqueMPgraphic{CircularShade}] +%D \defineoverlay[demo 2][\uniqueMPgraphic {LinearShade}] +%D \defineoverlay[demo 3][\uniqueMPgraphic {DuotoneShade}] +%D \stopbuffer +%D +%D \typebuffer +%D +%D \getbuffer +%D +%D These backgrounds can for instance be applied to \type +%D {\framed}: +%D +%D \startbuffer +%D \setupframed[width=3cm,height=2cm,frame=off] +%D \startcombination[3*1] +%D {\framed[backgroundachtergrond=demo 1]{\bfd \white Demo 1}} {} +%D {\framed[backgroundachtergrond=demo 2]{\bfd \white Demo 2}} {} +%D {\framed[backgroundachtergrond=demo 3]{\bfd \white Demo 3}} {} +%D \stopcombination +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlinecorrection +%D \getbuffer +%D \stoplinecorrection +%D +%D There are a few more alternatives, determined by the second +%D parameter passed to \type {circular_shade} and alike. +%D +%D \def\SomeShade#1#2#3#4#5% +%D {\startuniqueMPgraphic{Shade-#1} +%D width := \overlaywidth ; +%D height := \overlayheight ; +%D path p ; p := unitsquare xscaled width yscaled height ; +%D #2_shade(p,#3,#4,#5) ; +%D \stopuniqueMPgraphic +%D \defineoverlay[Shade-#1][\uniqueMPgraphic{Shade-#1}]% +%D \framed[backgroundachtergrond=Shade-#1,width=2cm,height=2cm,frame=off]{}} +%D +%D \startlinecorrection +%D \startcombination[5*1] +%D {\SomeShade{10}{circular}{0}{.3blue}{.9blue}} {circular 0} +%D {\SomeShade{11}{circular}{1}{.3blue}{.9blue}} {circular 1} +%D {\SomeShade{12}{circular}{2}{.3blue}{.9blue}} {circular 2} +%D {\SomeShade{13}{circular}{3}{.3blue}{.9blue}} {circular 3} +%D {\SomeShade{14}{circular}{4}{.3blue}{.9blue}} {circular 4} +%D \stopcombination +%D \stoplinecorrection +%D +%D \blank +%D +%D \startlinecorrection +%D \startcombination[5*1] +%D {\SomeShade{20}{circular}{0}{.9green}{.3green}} {circular 0} +%D {\SomeShade{21}{circular}{1}{.9green}{.3green}} {circular 1} +%D {\SomeShade{22}{circular}{2}{.9green}{.3green}} {circular 2} +%D {\SomeShade{23}{circular}{3}{.9green}{.3green}} {circular 3} +%D {\SomeShade{24}{circular}{4}{.9green}{.3green}} {circular 4} +%D \stopcombination +%D \stoplinecorrection +%D +%D \blank +%D +%D \startlinecorrection +%D \startcombination[4*1] +%D {\SomeShade{30}{linear}{0}{.3red}{.9red}} {linear 0} +%D {\SomeShade{31}{linear}{1}{.3red}{.9red}} {linear 1} +%D {\SomeShade{32}{linear}{2}{.3red}{.9red}} {linear 2} +%D {\SomeShade{33}{linear}{3}{.3red}{.9red}} {linear 3} +%D \stopcombination +%D \stoplinecorrection +%D +%D These macros closely cooperate with the \METAPOST\ module +%D \type {mp-spec.mp}, which is part of the \CONTEXT\ +%D distribution. +%D +%D The low level (\PDF) implementation is based on the \TEX\ +%D based \METAPOST\ to \PDF\ converter. Shading is supported +%D by overloading the \type {fill} operator as implemented +%D earlier. In \PDF\ type~2 and~3 shading functions are +%D specified in terms of: +%D +%D \starttabulate[|Tl|l|] +%D \NC /Domain \NC sort of meeting range \NC \NR +%D \NC /C0 \NC inner shade \NC \NR +%D \NC /C1 \NC outer shade \NC \NR +%D \NC /N \NC smaller values, bigger inner circles \NC \NR +%D \stoptabulate + +\newcount\currentPDFshade % 0 % global (document wide) counter +\let\currentMPshades\empty + +\def\startMPshading#1% + {\edef\currentMPspecial{\gMPs{#1}}} + +\def\stopMPshading + {\global\advance\currentPDFshade \plusone + \setxvalue{obj:Sh:\currentMPspecial}% + {/Sh\the\currentPDFshade\space\the\pdflastobj\space0 R }% + \setxvalue{mps:Sh:\currentMPspecial}% + {\the\currentPDFshade}} + +\appendtoks + \global\let\currentMPshades\empty +\to \MPstartresources + +\appendtoks + \ifx\currentMPshades\empty \else + \xdef\currentPDFresources{\currentPDFresources + /Shading <<\currentMPshades>>}% + \fi +\to \MPstopresources + +\def\invokeMPshadespecial + {\ifundefined{mps:Sh:\currentMPspecial}\else + \edef\currentMPshade{\getvalue{obj:Sh:\currentMPspecial}}% + \doifinstringelse\currentMPshade\currentMPshades \donothing + {\xdef\currentMPshades{\currentMPshades\currentMPshade}}% + \def\extraMPpathcode{/Sh\getvalue{mps:Sh:\currentMPspecial} sh Q}% + \chardef\finiMPpath\zerocount + \PDFcode{q /Pattern cs}% + \fi} + +\appendtoks \invokeMPshadespecial \to \invokeMPspecials + +%D We need to convert the \CMYK\ specials into colors, because +%D we have to do it twice, we define a macro. + +\def\checkMPshadingcolor#1#2#3#4#5% + {\edef\tempMPrvalue{\csname\@@MP0#1\endcsname}% + \edef\tempMPgvalue{\csname\@@MP0#2\endcsname}% + \edef\tempMPbvalue{\csname\@@MP0#3\endcsname}% + \global\let\MPresolvedspace\MPgrayspace + \global\let\MPresolvedcolor\!!zerocount + \ifnum\MPrgbnumber\tempMPrvalue=\MPspecialsignal\relax + \ifcase\MPrgbnumber\tempMPgvalue + \or % 1 = cmyk + \ifMPcmykcolors + \expanded{\resolveMPcmykcolor\getvalue{\@@MPSK\number\MPrgbnumber\tempMPbvalue}}\end + \fi + \or % 2 = spot + \ifMPspotcolors + \expanded{\resolveMPspotcolor\getvalue{\@@MPSP\number\MPrgbnumber\tempMPbvalue}}\end + \fi + \or + % 3 = rgb transparency + % to do + \or + % 4 == cmyk transparency + % \ifMPcmykcolors + % to do + % \fi + \or + % 5 == spot transparency + % \ifMPspotcolors + % to do + % \fi + \fi + \else + \ifx\tempMPrvalue\tempMPgvalue + \ifx\tempMPrvalue\tempMPbvalue + \expanded{\resolveMPgraycolor\tempMPbvalue}\end + \else + \expanded{\resolveMPrgbcolor\tempMPrvalue\space\tempMPgvalue\space\tempMPbvalue}\end + \fi + \else + \expanded{\resolveMPrgbcolor\tempMPrvalue\space\tempMPgvalue\space\tempMPbvalue}\end + \fi + \fi + \let#4\MPresolvedcolor + \let#5\MPresolvedspace} + +%D We also need to make sure that we have two \RGB\ or +%D \CMYK colors, since we have to set the colorspace. + +\def\setMPshadingcolors#1#2#3#4#5#6% color space + {\checkMPshadingcolor{#1}{#2}{#3}\MPshadeAc\MPshadeAs + \checkMPshadingcolor{#4}{#5}{#6}\MPshadeBc\MPshadeBs + \ifx\MPshadeAs\MPshadeBs + \let\MPshadeA\MPshadeAc + \let\MPshadeB\MPshadeBc + \let\MPshadeC\MPshadeAs + \else\ifx\MPshadeAs\MPgrayspace + \ifx\MPshadeBs\MPrgbspace + \edef\MPshadeA{\MPshadeAc\space\MPshadeAc\space\MPshadeAc}% + \else + \negatecolorcomponent\MPshadeAc + \edef\MPshadeA{0 0 0 \MPshadeAc}% + \fi + \let\MPshadeB\MPshadeBc + \let\MPshadeC\MPshadeBs + \else\ifx\MPshadeBs\MPgrayspace + \let\MPshadeA\MPshadeAc + \ifx\MPshadeAs\MPrgbspace + \edef\MPshadeB{\MPshadeBc\space\MPshadeBc\space\MPshadeBc}% + \else + \negatecolorcomponent\MPshadeBc + \edef\MPshadeB{0 0 0 \MPshadeBc}% + \fi + \let\MPshadeC\MPshadeAs + \else + % different color spaces + \def\MPshadeA{1}% + \def\MPshadeB{1}% + \let\MPshadeC\MPgrayspace + \fi\fi\fi} + +\let\MPshadeA\MPcmykWhite +\let\MPshadeB\MPcmykBlack +\let\MPshadeC\MPgrayspace + +%D The reason why this macro is a bit complicates is that we +%D handle black and white situations (otherwise we would have +%D to use \CMYK\ b/w in case of a \CMYK\ shade). + +%D Here are the special handlers: + +\defineMPspecial{30} + {\startMPshading{14}% type 2 + \setMPshadingcolors{4}{5}{6}{9}{10}{11}% + \immediate\pdfobj + {<</FunctionType 2 + /Domain [\gMPs1 \gMPs2] + /C0 [\MPshadeA] + /C1 [\MPshadeB] + /N \gMPs3>>}% + \immediate\pdfobj + {<</ShadingType 2 + /ColorSpace /\MPshadeC\space + /Function \the\pdflastobj\space 0 R + /Coords [\gMPs7 \gMPs8 \gMPs{12} \gMPs{13}] + /Extend [true true]>>}% + \stopMPshading} + +\defineMPspecial{31} + {\startMPshading{16}% type 3 + \setMPshadingcolors{4}{5}{6}{10}{11}{12}% + \immediate\pdfobj + {<</FunctionType 2 + /Domain [\gMPs1 \gMPs2] + /C0 [\MPshadeA] + /C1 [\MPshadeB] + /N \gMPs3>>}% + \immediate\pdfobj + {<</ShadingType 3 + /ColorSpace /\MPshadeC\space + /Function \the\pdflastobj\space 0 R + /Coords [\gMPs7 \gMPs8 \gMPs9 \gMPs{13} \gMPs{14} \gMPs{15}] + /Extend [true true]>>}% + \stopMPshading} + +%D Figure inclusion is kind of strange to \METAPOST, but when +%D Santiago Muelas started discussing this with me, I was able +%D to cook up a solution using specials. + +\def\invokeMPfigurespecial% + {\getvalue{mps:gr:\currentMPspecial}} % or \relax + +\appendtoks \invokeMPfigurespecial \to \invokeMPspecials + +\defineMPspecial{10} + {\setxvalue{mps:gr:\gMPs8}% + {\noexpand\handleMPfigurespecial + {\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}% + \noexpand\setxvalue{mps:gr:\gMPs8}{}}} + +\def\handleMPfigurespecial#1#2#3#4#5#6#7% todo : combine with ext fig + {\vbox to \zeropoint + {\vss + \hbox to \zeropoint + {\ifcase\pdfoutput\or % will be hooked into the special driver + \doiffileelse{#7} + {\doifundefinedelse{mps:x:#7} + {\immediate\pdfximage\!!width\onebasepoint\!!height\onebasepoint{#7}% + \setxvalue{mps:x:#7}{\pdfrefximage\the\pdflastximage}}% + {\message{[reusing figure #7]}}% + \PDFcode{q #1 #2 #3 #4 #5 #6 cm}% + \rlap{\getvalue{mps:x:#7}}% + \PDFcode{Q}} + {\message{[unknown figure #7]}}% + \fi + \hss}}} + +%D An example of using both special features is the +%D following. +%D +%D \starttyping +%D \startMPpage +%D externalfigure "hakker1b.png" scaled 22cm rotated 10 shifted (-2cm,0cm); +%D externalfigure "hakker1b.png" scaled 10cm rotated -10 ; +%D externalfigure "hakker1b.png" scaled 7cm rotated 45 shifted (8cm,12cm) ; +%D path p ; p := unitcircle xscaled 15cm yscaled 20cm; +%D path q ; q := p rotatedaround(center p,90) ; +%D path r ; r := buildcycle(p,q) ; clip currentpicture to r ; +%D path s ; s := boundingbox currentpicture enlarged 5mm ; +%D picture c ; c := currentpicture ; currentpicture := nullpicture ; +%D circular_shade(s,0,.2red,.9red) ; +%D addto currentpicture also c ; +%D \stopMPpage +%D \stoptyping + +%D This is some experimental hyperlink driver that I wrote +%D for Mark Wicks. + +\defineMPspecial{20} + {\setxvalue{mps:hl:\gMPs6}% + {\noexpand\handleMPhyperlink + {\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}% + \noexpand\setxvalue{mps:hl:\gMPs6}{}}} + +\def\handleMPhyperlink#1#2#3#4#5% + {%\ifcase\pdfoutput\or + \setbox\scratchbox\hbox + {\setbox\scratchbox\null + \scratchdimen#1\onebasepoint\scratchdimen-\scratchdimen + \advance\scratchdimen#3\onebasepoint + \wd\scratchbox\scratchdimen + \scratchdimen#2\onebasepoint\scratchdimen-\scratchdimen + \advance\scratchdimen#4\onebasepoint + \ht\scratchbox\scratchdimen + \incolorfalse + \gotobox{\box\scratchbox}[#5]}% + \setbox\scratchbox\hbox + {\scratchdimen\MPxoffset\onebasepoint\advance\scratchdimen#1\onebasepoint + \hskip\scratchdimen + \scratchdimen\MPyoffset\onebasepoint\advance\scratchdimen#2\onebasepoint + \raise\scratchdimen\box\scratchbox}% + \smashbox\scratchbox + \box\scratchbox + }%\fi} + +\def\invokeMPhyperlinkspecial% + {\getvalue{mps:hl:\currentMPspecial}} % or \relax + +\appendtoks \invokeMPhyperlinkspecial \to \invokeMPspecials + +%D Special number~1 is dedicated to \CMYK\ support. If you +%D want to know why: look at this: +%D +%D \startbuffer[mp] +%D fill fullcircle xyscaled (3cm,1cm) withcolor \MPcolor{test} ; +%D \stopbuffer +%D +%D \startbuffer[cmyk] +%D \startcombination[4*1] +%D {\definecolor[test][c=1,y=.3,k=.3] \processMPbuffer[mp]} {c=1 y=.3 k=.3} +%D {\definecolor[test][c=.9,y=.15] \processMPbuffer[mp]} {c=.9 y=.15} +%D {\definecolor[test][c=.25,y=.8] \processMPbuffer[mp]} {c=.25 y=.8} +%D {\definecolor[test][c=.45,y=.1] \processMPbuffer[mp]} {c=.45 y=.1} +%D \stopcombination +%D \stopbuffer +%D +%D \placefigure +%D {\CMYK\ support disabled, +%D conversion to \RGB.} +%D {\setupcolors[cmyk=nee,state=start]\getbuffer[cmyk]} +%D +%D \placefigure +%D {\CMYK\ support enabled, +%D no support in \METAPOST.} +%D {\setupcolors[cmyk=ja,mpcmyk=nee,state=start]\getbuffer[cmyk]} +%D +%D \placefigure +%D {\CMYK\ support enabled, +%D no conversion to \RGB, +%D support in \METAPOST} +%D {\setupcolors[cmyk=ja,state=start]\getbuffer[cmyk]} + +\defineMPspecial{1} + {\ifMPcmykcolors + \setxvalue{\@@MPSK\gMPs1}{\gMPs2 \gMPs3 \gMPs4 \gMPs5 }% + \fi} + +\def\setMPcmyk#1 #2 #3 #4 % + {\setvalue{\@@MP01}{#1}% + \setvalue{\@@MP02}{#2}% + \setvalue{\@@MP03}{#3}% + \setvalue{\@@MP04}{#4}} + +\defineMPspecial{2} + {\ifMPspotcolors + \setxvalue{\@@MPSP\gMPs1}{\gMPs2 \gMPs3 \gMPs4 \gMPs5 }% space is essential + \checkMPspot{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}% + \fi} + +\def\setMPspot#1 #2 #3 #4 % + {\setvalue{\@@MP01}{#1}% + \setvalue{\@@MP02}{#2}% + \setvalue{\@@MP03}{#3}% + \setvalue{\@@MP04}{#4}} + +\def\checkMPspot#1#2#3#4% + {\expanded{\resolveMPspotcolor#1 #2 #3 #4}\end + \ifx\MPspotspace\MPresolvedspace + \edef\MPspotspacespec{/\MPspotspace\space}% + \doifinstringelse\MPspotspacespec\currentMPcolorspaces + \donothing\registerMPcolorspace + \fi} + +%D This special (number 50) passes positions to a tex file. +%D This method uses a two||pass approach an (mis|)|used the +%D context positioning macros. In \type {core-pos} we will +%D implement the low level submacro needed. +%D +%D \startbuffer +%D \definelayer[test] +%D +%D \setlayer +%D [test] +%D [x=\MPx{somepos-1},y=\MPy{somepos-1}] +%D {Whatever we want here!} +%D +%D \setlayer +%D [test] +%D [x=\MPx{somepos-2},y=\MPy{somepos-2}] +%D {Whatever we need there!} +%D +%D \startuseMPgraphic{oeps} +%D draw fullcircle scaled 6cm withcolor red ; +%D register ("somepos-1",1cm,2cm,center currentpicture) ; +%D register ("somepos-2",4cm,3cm,(-1cm,-2cm)) ; +%D \stopuseMPgraphic +%D +%D \framed[background=test,offset=overlay]{\useMPgraphic{oeps}} +%D \stopbuffer +%D +%D \typebuffer +%D +%D Here the width and height are not realy used, but one can +%D imagine situations where tex has to work with values +%D calculated by \METAPOST. +%D +%D \startlinecorrection +%D \getbuffer +%D \stoplinecorrection +%D +%D Later we will implement a more convenient macro: +%D +%D \starttyping +%D \setMPlayer [test] [somepos-1] {Whatever we want here!} +%D \setMPlayer [test] [somepos-2] {Whatever we need there!} +%D \stoptyping + +\ifx\dosavepositionwhd\undefined + \let\dosavepositionwhd\gobblesevenarguments +\fi + +\defineMPspecial{50} % x y width height label + {\bgroup + \scratchdimen\MPllx\onebasepoint\scratchdimen-\scratchdimen + % \scratchdimen-\MPllx\onebasepoint % moet ook werken + \advance\scratchdimen\gMPs1\onebasepoint + \edef\x{\number\scratchdimen}% + \scratchdimen\gMPs2\onebasepoint + \scratchdimen-\scratchdimen + \advance\scratchdimen\MPury\onebasepoint + \edef\y{\number\scratchdimen}% + \scratchdimen\gMPs3\onebasepoint + \edef\w{\number\scratchdimen}% + \scratchdimen\gMPs4\onebasepoint + \edef\h{\number\scratchdimen}% + \dosavepositionwhd{\gMPs5}0\x\y\w\h0% + \egroup} + +%D Transparency support used specials 60 (rgb) and 61 +%D (cmyk). +%D +%D \startbuffer +%D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0); +%D +%D fill p rotated 90 withcolor transparent(1,.5,yellow) ; +%D fill p rotated 210 withcolor transparent(1,.5,green) ; +%D fill p rotated 330 withcolor transparent(1,.5,blue) ; +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startlinecorrection \processMPbuffer \stoplinecorrection +%D +%D One can also communicate colors between \CONTEXT\ and +%D \METAPOST: +%D +%D \startbuffer +%D \definecolor[tcyan] [c=1,k=.2,t=.5] +%D \definecolor[tmagenta][m=1,k=.2,t=.5] +%D \definecolor[tyellow] [y=1,k=.2,t=.5] +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0); +%D +%D fill p rotated 90 withcolor \MPcolor{tcyan} ; +%D fill p rotated 210 withcolor \MPcolor{tmagenta} ; +%D fill p rotated 330 withcolor \MPcolor{tyellow} ; +%D \stopbuffer +%D +%D \startlinecorrection \processMPbuffer \stoplinecorrection +%D +%D We save all the three components needed in one macro, +%D just to save hash space. + +\def\@@MPST{@MPST@} + +\def\assignMPStransparency#1#2#3% + {\edef\PDFtransparencyidentifier{#1}% + \edef\PDFtransparencyreference {#2}% + \edef\PDFtransparencycolorspecs{#3}} + +\def\PDFtransparencyspec % todo + {\ifx\MPresolvedspace\MPgrayspace + \MPresolvedcolor\space g + \MPresolvedcolor\space G% + \else\ifx\MPresolvedspace\MPrgbspace + \MPresolvedcolor\space rg + \MPresolvedcolor\space RG% + \else\ifx\MPresolvedspace\MPcmykspace + \MPresolvedcolor\space k + \MPresolvedcolor\space K% + \else\ifx\MPresolvedspace\empty\else + /\MPresolvedspace\space cs + /\MPresolvedspace\space CS + \PDFgetspotcolorspec\MPresolvedcolor + \fi\fi\fi\fi} + +\defineMPspecial{3} % rgb + {\edef\currentMPspecial{\gMPs6}% + \presetPDFtransparency{\gMPs1}{\gMPs2}% + \expanded{\resolveMPrgbcolor\gMPs3 \gMPs4 \gMPs5}\end + \setevalue{\@@MPST\currentMPspecial}% was \setxvalue, bug ! + {\noexpand\assignMPStransparency + {\PDFtransparencyidentifier}% + {\PDFtransparencyreference}% + {\PDFtransparencyspec}}} + +\defineMPspecial{4} % cmyk + {\edef\currentMPspecial{\gMPs7}% + \presetPDFtransparency{\gMPs1}{\gMPs2}% + \expanded{\resolveMPcmykcolor\gMPs3 \gMPs4 \gMPs5 \gMPs6}\end + \setevalue{\@@MPST\currentMPspecial}% was \setxvalue, bug ! + {\noexpand\assignMPStransparency + {\PDFtransparencyidentifier}% + {\PDFtransparencyreference}% + {\PDFtransparencyspec}}} + +\defineMPspecial{5} % spot + {\edef\currentMPspecial{\gMPs7}% + \presetPDFtransparency{\gMPs1}{\gMPs2}% + \checkMPspot{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}% + \setevalue{\@@MPST\currentMPspecial}% was \setxvalue, bug ! + {\noexpand\assignMPStransparency + {\PDFtransparencyidentifier}% + {\PDFtransparencyreference}% + {\PDFtransparencyspec}}} + +% beware: for the moment only supported in pdftex; needs a cleanup! + +\def\registerMPcolorspace + {\doifobjectreferencefoundelse{PDFCS}\MPspotspace + {\doPDFgetobjectreference{PDFCS}\MPspotspace\PDFobjectreference + \xdef\currentMPcolorspaces + {\currentMPcolorspaces\MPspotspacespec\PDFobjectreference\space}} + \donothing} + +%D We need to add resource specifications! + +\appendtoks + \global\let\currentMPcolorspaces\empty +\to \MPstartresources + +\appendtoks + \ifx\currentMPcolorspaces\empty \else + \xdef\currentPDFresources{\currentPDFresources + /ColorSpace <<\currentMPcolorspaces>>}% + \fi +\to \MPstopresources + +%D For efficiency reasons, we fall back on the allocation +%D mechanisms already present. For use within \MPTOPDF, we +%D provide a fall back routine. + +\let\currentMPtransparencies\empty + +% this one triggers a new graphic state + +\def\invokeMPtransparencyspecial + {\scratchcounter\MPrgbnumber\lastMPbvalue + \edef\currentMPspecial{\the\scratchcounter}% + \ifundefined{\@@MPST\currentMPspecial}\else + \getvalue{\@@MPST\currentMPspecial}% + \doifinstringelse\PDFtransparencyidentifier\currentMPtransparencies + \donothing\registerMPtransparencyresource % slow + \PDFcode + {\PDFtransparencycolorspecs\space + \PDFtransparencyidentifier\space gs}% + % potential optimization + % \setevalue{\@@MPST\currentMPspecial}% + % {\PDFcode + % {\PDFtransparencycolorspecs\space + % \PDFtransparencyidentifier\space gs}}% + % \getvalue{\@@MPST\currentMPspecial}% + \let\revokeMPtransparencyspecial\dorevokeMPtransparencyspecial + \fi} + +% this one does a reset + +\let\revokeMPtransparencyspecial\relax + +\appendtoks + \revokeMPtransparencyspecial +\to \MPstopresources + +\def\dorevokeMPtransparencyspecial % only called if state is set + {\ifx\PDFtransparencyresetidentifier\empty\else + \doifinstringelse\PDFtransparencyresetidentifier\currentMPtransparencies + \donothing\registerMPtransparencyresetresource + \PDFcode{\PDFtransparencyresetidentifier\space gs}% + % potential optimization + % \def\dorevokeMPtransparencyspecial + % {\PDFcode + % {\PDFtransparencycolorspecs\space + % \PDFtransparencyidentifier\space gs}}% + \let\dorevokeMPtransparencyspecial\dodorevokeMPtransparencyspecial + \let\revokeMPtransparencyspecial\relax % invoke sets it + \fi} + +% and this one does a simplified reset + +\def\dodorevokeMPtransparencyspecial % used after first invocation + {\PDFcode{\PDFtransparencyresetidentifier\space gs}% + \let\revokeMPtransparencyspecial\relax} % invoke sets it + +% add a resource entry + +\def\registerMPtransparencyresource + {\xdef\currentMPtransparencies + {\currentMPtransparencies + \PDFtransparencyidentifier\space + \PDFtransparencyreference\space}} + +\def\registerMPtransparencyresetresource + {\xdef\currentMPtransparencies + {\currentMPtransparencies + \PDFtransparencyresetidentifier\space + \PDFtransparencyresetreference\space}} + +\appendtoks \invokeMPtransparencyspecial \to \invokeMPspecials + +\ifCONTEXT \else + + \def\@@MPSTN{@MPSTN@} + \def\@@MPSTO{@MPSTO@} + + \newcount\PDFcurrenttransparency + + \let\PDFtransparencyresetidentifier\empty + \let\PDFtransparencyresetreference \empty + + \let\PDFtransparencyidentifier\empty + \let\PDFtransparencyreference \empty + + \def\initializePDFtransparency + {\global\let\initializePDFtransparency\relax + \presetPDFtransparency{1}{1}% + \xdef\PDFtransparencyresetidentifier{/Tr0}% + \xdef\PDFtransparencyresetreference{\the\pdflastobj\space 0 R}} + + \def\presetPDFtransparency#1#2% + {\initializePDFtransparency + \@EA\ifx\csname\@@MPSTO#1:#2\endcsname\relax + \global\advance\PDFcurrenttransparency \plusone + \immediate\pdfobj{\PDFtransparencydictionary{#1}{#2}{}}% + \setxvalue{\@@MPSTN#1:#2}{\the\PDFcurrenttransparency}% + \setxvalue{\@@MPSTO#1:#2}{\the\pdflastobj}% + \fi + \edef\PDFtransparencyidentifier{/Tr\getvalue{\@@MPSTN#1:#2}}% + \edef\PDFtransparencyreference{\getvalue{\@@MPSTO#1:#2} 0 R}} + + \def\PDFtransparencydictionary#1#2#3% type fraction extras + {<</Type /ExtGState + /ca #2 /CA #2 + /BM /\ifcase#1 Normal\or Normal\or Multiply\or Screen\or + Overlay\or SoftLight\or HardLight\or ColorDodge\or + ColorBurn\or Darken\or Lighten\or Difference\or + Exclusion\else Compatible\fi + #3>>} + +\fi + +\appendtoks + \global\let\currentMPtransparencies\empty +\to \MPstartresources + +\appendtoks + \ifx\currentMPtransparencies\empty \else + \xdef\currentPDFresources{\currentPDFresources + /ExtGState <<\currentMPtransparencies>>}% + \fi +\to \MPstopresources + +%D In all cases, we need to keep track of the resources +%D used. + +%D A few auxiliary macros: + +\def\MPgrayspace{DeviceGray} +\def\MPrgbspace {DeviceRGB} +\def\MPcmykspace{DeviceCMYK} +\let\MPspotspace\MPgrayspace + +\def\MPcmykBlack{0 0 0 0} +\def\MPcmykWhite{0 0 0 1} + +\ifCONTEXT + + \def\startMPcolorresolve + {\bgroup + \def\dostartgraycolormode##1% + {\global\let\MPresolvedspace\MPgrayspace + \xdef\MPresolvedcolor{##1}}% + \def\dostartrgbcolormode ##1##2##3% + {\global\let\MPresolvedspace\MPrgbspace + \xdef\MPresolvedcolor{##1 ##2 ##3}}% + \def\dostartcmykcolormode##1##2##3##4% + {\global\let\MPresolvedspace\MPcmykspace + \xdef\MPresolvedcolor{##1 ##2 ##3 ##4}}% + \def\dostartspotcolormode##1##2% + {\global\let\MPspotspace\empty + \xdef\MPresolvedspace{##1}% + \xdef\MPresolvedcolor{##2}% + \global\let\MPspotspace\MPresolvedspace}% signal + \dostartgraycolormode\!!zerocount} % kind of hackery initialization + + \let\stopMPcolorresolve\egroup + + \def\resolveMPrgbcolor#1 #2 #3\end + {\startMPcolorresolve + \execcolorR#1:#2:#3:0:0\od + \stopMPcolorresolve} + + \def\resolveMPcmykcolor#1 #2 #3 #4\end + {\startMPcolorresolve + \execcolorC#1:#2:#3:#4:0:0\od + \stopMPcolorresolve} + + \def\resolveMPgraycolor#1\end + {\startMPcolorresolve + \execcolorS#1:0:0\od + \stopMPcolorresolve} + + \def\resolveMPspotcolor#1 #2 #3 #4\end + {\startMPcolorresolve + \ifnum#2>\plusone + \checkmultitonecolor{#1}% + \fi + \execcolorP#1:#2:#3:#4:0:0\od + \stopMPcolorresolve} + +\else + + \def\resolveMPspotcolor#1 #2\end + {\global\let\MPresolvedspace\MPgrayspace + \xdef\MPresolvedcolor{0}} + + \def\resolveMPrgbcolor#1 #2 #3\end + {\global\let\MPresolvedspace\MPrgbspace + \xdef\MPresolvedcolor{#1 #2 #3}} + + \def\resolveMPcmykcolor#1 #2 #3 #4\end + {\global\let\MPresolvedspace\MPcmykspace + \xdef\MPresolvedcolor{#1 #2 #3 #4}} + + \def\resolveMPgraycolor#1\end + {\global\let\MPresolvedspace\MPgrayspace + \xdef\MPresolvedcolor{#1}} % should be inverted + +\fi + +\protect \endinput diff --git a/tex/context/base/page-flt.tex b/tex/context/base/page-flt.tex index 3cc61d291..30a337443 100644 --- a/tex/context/base/page-flt.tex +++ b/tex/context/base/page-flt.tex @@ -134,11 +134,11 @@ 2: -- lagret 3: -- flyttet 4: -- plassert - 5: rekkefølge tilpasset - 6: maksimalt -- flytblokker øverst + 5: rekkefølge tilpasset + 6: maksimalt -- flytblokker øverst 7: maksimalt -- flytblokker nederst 8: mindre enn -- linjer - 9: rekkefølge endret + 9: rekkefølge endret 10: -- begrenset 11: ingen blokk oppgitt 12: udefinert @@ -1370,6 +1370,7 @@ \fi} \def\placefloatcaptiontext [#1]{\getvalue{@fl@t@#1}} +\def\placefloatcaptionnumber [#1]{\getvalue{@fl@n@#1}} \def\placefloatcaptionreference[#1]{\getvalue{@fl@r@#1}} % still needed for uguide @@ -2216,11 +2217,17 @@ \getparameters[\??si][#1]% \resetnumber[\??si]% \def\floatcaptionsuffix{\convertednumber[\??si]}% - \TABLEcaptionheight\@@silines\lineheight % brrr + % \TABLEcaptionheight\@@silines\lineheight% brrr +% todo: auto == \getnoflines\captionheight +\let\extrasplitfloatlines\@@silines +\the\everysplitfloatsetup \simplifypagebreak % \page becomes \goodbreak +% todo: a preceding float does not count yet +% so we need a better predictor \dowithnextbox {\forgetall \dontcomplain +\chardef\nodelocationmode\zerocount \doloop {\setbox2\vsplit\nextbox to \lineheight \setbox2\vbox{\unvbox2} @@ -2234,10 +2241,12 @@ \egroup \ifdim\nextboxht>\zeropoint \page - \decrementnumber[\floatcaptionnumber]% \fi \fi - \ifdim\nextboxht>\zeropoint\else + \ifdim\nextboxht>\zeropoint +\decrementnumber[\floatcaptionnumber] +%\setupnumber[\floatcaptionnumber][\c!state=\v!stop]% + \else \expandafter\exitloop \fi}% \egroup} @@ -2247,6 +2256,26 @@ \def\splitfloat {\dosingleempty\dosplitfloat} +\newtoks \everysplitfloatsetup + +% will move to core-tab + +\appendtoks + \TABLEcaptionheight\extrasplitfloatlines\lineheight +\to \everysplitfloatsetup + +% will move to core-ntb + +\appendtoks + \def\extratblsplitheight{\extrasplitfloatlines\lineheight}% +\to \everysplitfloatsetup + +% todo in core-tbl + +\appendtoks + % set extra +\to \everysplitfloatsetup + % \splitfloat [settings] {\placetable[optional args]{test}} {content} \def\dooutput{\sidefloatoutput} % redefinition of \dooutput diff --git a/tex/context/base/page-ini.tex b/tex/context/base/page-ini.tex index 5184df72a..ee62d92bb 100644 --- a/tex/context/base/page-ini.tex +++ b/tex/context/base/page-ini.tex @@ -155,10 +155,10 @@ 1: caricamento dei file supplementari posticipato (typemode) 2: -- caricato % 3: provare LaTeX - 4: comando -- già definito + 4: comando -- già definito 5: macro del modulo -- caricate 6: nessuna macro trovata nel modulo -- - 7: macro del modulo -- già caricate + 7: macro del modulo -- già caricate 8: nuova versione del file supplementare, seconda passata necessaria 9: -- non trovato/elaborato 10: non usare em in -- @@ -185,12 +185,12 @@ title: system 1: innlesning av hjelpefila utsatt (typemode) 2: -- er lest inn -% 3: forsøker LaTeX +% 3: forsøker LaTeX 4: kommando -- er allerede definert 5: makroene i modul -- er lest inn 6: ingen makroer funnet i modul --- 7: makroene i modul -- er allerede lest inn - 8: ny versjon av hjelpefil, andre gjennomkjøring nødvendig + 8: ny versjon av hjelpefil, andre gjennomkjøring nødvendig 9: -- ikke funnet/behandlet 10: ikke bruk em i -- 11: lager enkel hjelpefil @@ -205,7 +205,7 @@ 20: betydning (sorterer) av -- er lest inn 21: hjelpefila er ikke lest inn 22: bruk en gyldig hjelpefil - 23: -- arrangert på -- + 23: -- arrangert pÃ¥ -- 24: Flytblokker 25: Referanser 26: Registere @@ -346,12 +346,12 @@ \startmessages norwegian library: layouts title: layout - 1: teksthøyde tilpasset med -- på side -- - 2: -- ganger forskjøvet tekst plassert - 3: -- ganger tekst forskjøvet + 1: teksthøyde tilpasset med -- pÃ¥ side -- + 2: -- ganger forskjøvet tekst plassert + 3: -- ganger tekst forskjøvet 4: margblokker aktive 5: margblokker inaktive - 6: delside sett -- behandlet (størrelse --) + 6: delside sett -- behandlet (størrelse --) % 7: beregner plass for logo % 8: beregner bakgrunn 10: -- og -- er ikke 1.0 til sammen @@ -577,17 +577,17 @@ title: kolonner 1: maksimalt -- kolonner 2: bruk \string\filbreak\space som et alternativ - 3: problemer, slår av balansering - 4: flytblokker øverst er ikke støttet enda - 5: flytblokker nedert er ikke støttet enda - 6: -- flytblokk forskjøvet + 3: problemer, slÃ¥r av balansering + 4: flytblokker øverst er ikke støttet enda + 5: flytblokker nedert er ikke støttet enda + 6: -- flytblokk forskjøvet 7: balansering avbrutt etter 100 iterasjoner 8: balansert etter -- iterasjoner 9: kontroller tekstlayout! 10: (mindre enn) 1 linje igjen 11: flytblokk for bredt for kolonna - 12: flytblokk forskjøvet til neste kolonne / -- - 13: bred flytblokk forksjøvet til toppen av kolonnene + 12: flytblokk forskjøvet til neste kolonne / -- + 13: bred flytblokk forksjøvet til toppen av kolonnene \stopmessages \startmessages romanian library: columns diff --git a/tex/context/base/sort-ini.tex b/tex/context/base/sort-ini.tex index 86f3091c0..970cbff1f 100644 --- a/tex/context/base/sort-ini.tex +++ b/tex/context/base/sort-ini.tex @@ -74,6 +74,8 @@ \unprotect +\newevery \everysavesortkeys \relax + \let\currentexportclass\empty \def\exportsortaction#1#2#3% @@ -101,15 +103,8 @@ \fi}% \egroup} -% Next we overload some macros defined in enco-ini and core-uti. This -% will change. - -\let\definesortkey\gobblefourarguments - -\def\savesortkeys - {\globallet\savesortkeys\relax - \enablemode[sortorder-\currentmainlanguage]% - \bgroup +\def\savesortdefinitions + {\bgroup \doifelse \currentregime {utf} {\exportutfsortexpansion{0}{128}{255}% \exportutfsortexpansion{1}{0}{255}} @@ -120,9 +115,36 @@ {\the\executeifdefined{\@reg@\characterencoding}\emptytoks}}% {\the\executeifdefined{\@reg@\characterregime}\emptytoks}}% \egroup - \readfile{\f!sortprefix new}\donothing\donothing % temporary hacks - \readfile{\f!sortprefix def}\donothing\donothing % defaults - \readfile{\f!sortprefix lan}\donothing\donothing}% language specifics + \readfile{\f!sortprefix def}\donothing\donothing % default + \global\let\savesortdefinitions\relax} + +\def\savesortlanguage#1% language specifics + {\doifsomething{#1} + {\doifundefined{\f!sortprefix::#1}% + {\bgroup + \global\letvalue{\f!sortprefix::#1}\empty + \def\currentexportclass{#1}% + \enablemode[sortorder-#1]% + \readfile{\f!sortprefix lan}\donothing\donothing + \egroup}}} + +\prependtoks + \savesortdefinitions +\to \everysavesortkeys + +\def\savesortkeys + {\the\everysavesortkeys + \global\everysavesortkeys\emptytoks} + +% \defineregister[one] +% \defineregister[two] \setupregister[two][language=cz] +% +% \starttext +% test \one{one} test \one{two} test \one {\aacute} test \one{alpha} test \one{chow} +% test \two{one} test \two{two} test \two {\aacute} test \two{alpha} test \two{chow} +% \blank[3*big] \placeregister[one] +% \blank[3*big] \placeregister[two] +% \stoptext % already done \prependtoks \savesortkeys \to \everystarttext diff --git a/tex/context/base/sort-lan.tex b/tex/context/base/sort-lan.tex index a4d77a6fa..ad5232b02 100644 --- a/tex/context/base/sort-lan.tex +++ b/tex/context/base/sort-lan.tex @@ -20,7 +20,6 @@ \exportsortexpansion{Agrave}{A+2} \stopmode - %D This module replaces existing sort key handling and is meant to be %D used with the new texutil functionality. Here we define the language %D specific sort rules. @@ -153,6 +152,9 @@ % c) sorting rule: "A" < "Á" < "a" < "á" < "C" < "c" < "C" < "c" % d) sorting rule: "h" < "ch" < "i" ("c" < "h") +\gdef\czsortdivisionch{ch} +\gdef\czsortdivisionCh{Ch} + \startmode[sortorder-cz] \exportsortexpansion {aacute} {a+1} \exportsortexpansion {Aacute} {A+1} @@ -160,7 +162,7 @@ \exportsortexpansion {Ccaron} {C+1} \exportsortdivision {c+1} {ccaron} \exportsortexpansion {dcaron} {d+1} - \exportsortexpansion {Dcaron} {C+1} + \exportsortexpansion {Dcaron} {D+1} \exportsortdivision {d+1} {dcaron} \exportsortexpansion {eacute} {e+1} \exportsortexpansion {Eacute} {E+1} @@ -168,13 +170,13 @@ \exportsortexpansion {Ecaron} {E+2} \exportsortreduction {ch} {h+1} \exportsortexpansion {ch} {h+1} - \exportsortreduction {Ch} {h+1} - \exportsortexpansion {Ch} {h+1} + \exportsortreduction {Ch} {H+1} + \exportsortexpansion {Ch} {H+1} \exportsortdivision {h+1} {czsortdivisionch} \exportsortexpansion {iacute} {i+1} \exportsortexpansion {Iacute} {I+1} \exportsortexpansion {ncaron} {n+1} - \exportsortexpansion {Ncaron} {n+1} + \exportsortexpansion {Ncaron} {N+1} \exportsortdivision {n+1} {ncaron} \exportsortexpansion {oacute} {o+1} \exportsortexpansion {Oacute} {O+1} diff --git a/tex/context/base/sort-new.tex b/tex/context/base/sort-new.tex deleted file mode 100644 index c7bea35a8..000000000 --- a/tex/context/base/sort-new.tex +++ /dev/null @@ -1,49 +0,0 @@ -% temporary overloading - -\unprotect - -\def\strippedcsname - {\expandafter\dostrippedcsname\string} - -\def\dostrippedcsname#1% - {\if\noexpand#1\letterbackslash\else#1\fi} - -\def\doregisterreference[#1]#2% - {\doifvalue{\??id#1\c!referencing}\v!on - {\pagereference[#1:\strippedcsname#2]}} - -\def\doprocesspageregister[#1]#2#3% key altnum entry - {\begingroup - \thisisnextinternal\s!ind - \ifduplicate\getlastregisterentry{#3}\fi - \convertexpanded{\registerparameter\c!keyexpansion}{#1}\asciiregisterentryA - \convertexpanded{\registerparameter\c!expansion }{#3}\asciiregisterentryB - \doifsomething{\registerparameter\c!keyexpansion} - {\ifx\asciiregisterentryA\empty - \convertexpanded{\registerparameter\c!keyexpansion}{#3}\asciiregisterentryA - \fi}% - \makesectionformat - \doifelse{\registerparameter\c!ownnumber}\v!yes - \donetrue\donefalse - % the spaces between } { are essential for texutil's split - \expanded - {\writeutility% - {r \ifcase\registerpagestatus\space\or e \or f \or t \fi - {\currentregister} % - {\nextinternalreference} % - {\asciiregisterentryA} % - {\asciiregisterentryB} % - {\sectionformat\sectionseparator\sectionseparator - \ifdone#2\else\noexpand\pagenumber\fi} % - {\noexpand\realfolio}}}% - \getfirstcharacter\currentregister - \registerinfo{> \firstcharacter}{#3}% - \endgroup} - -\def\reduceargument#1\to#2% - {\begingroup - \reducetocoding[raw]% - \edef\ascii{#1}% - \expandafter\endgroup\expandafter\edef\expandafter#2\expandafter{\ascii}} - -\protect diff --git a/tex/context/base/spec-ini.tex b/tex/context/base/spec-ini.tex index e455a6f21..8d867e9a1 100644 --- a/tex/context/base/spec-ini.tex +++ b/tex/context/base/spec-ini.tex @@ -80,9 +80,9 @@ \stopmessages \startmessages italian library: specials - title: specialità + title: specialitø 1: -- caricato - 2: non è permesso un annidamento maggiore -- + 2: non ø permesso un annidamento maggiore -- 3: -- reimpostato 4: il comando -- non esiste 5: caricamento del file di definizione -- @@ -144,7 +144,7 @@ \stopmessages \startmessages norwegian library: interactions - 21: -- kode satt inn / tilføyd + 21: -- kode satt inn / tilføyd \stopmessages \startmessages romanian library: interactions diff --git a/tex/context/base/supp-mps.tex b/tex/context/base/supp-mps.tex index d46de7fd4..b89483a5c 100644 --- a/tex/context/base/supp-mps.tex +++ b/tex/context/base/supp-mps.tex @@ -222,12 +222,26 @@ %D The next hack prevents too long lines: -\long\def\obeyMPlines - {\ifx\rawcharacter\undefined\else +\long\def\runtimeobeyMPlines + {\ifx\rawcharacter\undefined + \let\obeyedline\space + \else \obeylines - \def\obeyedline{\rawcharacter{10}}% + \ifx\systemendofline\undefined + \def\obeyedline{\rawcharacter{10}}% + \else + \let\obeyedline\systemendofline + \fi \fi} +\long\def\obeyMPlines % anyhow, we end up with ^^M's in the input + {\obeylines + \let\obeyedline\relax} % delay expansion + +\appendtoks + \let\obeyMPlines\runtimeobeyMPlines +\to \everydump + %D We use two distinguished token registers: \newtoks \MPextensions % once per run (can be multiple graphics) @@ -1089,7 +1103,7 @@ \def\executesystemcommand#1{\immediate\write18{#1}} \fi -\ifx\TEXEXECcommand \undefined \def\TEXEXECcommand{texexec} \fi +\ifx\TEXEXECcommand \undefined \def\TEXEXECcommand{texmfstart texexec} \fi \ifx\undefined\executeMetaPost diff --git a/tex/context/base/syst-con.tex b/tex/context/base/syst-con.tex index eedcde38b..cbef0dedc 100644 --- a/tex/context/base/syst-con.tex +++ b/tex/context/base/syst-con.tex @@ -192,7 +192,7 @@ \dorecurse{255} {\lccode`a=\recurselevel - \lowercase{\xdef\rawcharacter{\rawcharacter a\or}}} + \lowercase{\xdef\rawcharacter{\rawcharacter \string a\or}}} % string is needed for XeTeX \@EA\gdef\@EA\rawcharacter\@EA#\@EA1\@EA {\@EA\ifcase\@EA#\@EA1\rawcharacter\fi} diff --git a/tex/context/base/syst-ext.tex b/tex/context/base/syst-ext.tex index 40dfc27ec..82e6bc2e7 100644 --- a/tex/context/base/syst-ext.tex +++ b/tex/context/base/syst-ext.tex @@ -394,9 +394,21 @@ %D \stoptyping %D %D This expands to \type{\ifsomething}. +%D +%D \starttyping +%D \def\strippedcsname +%D {\expandafter\gobbleoneargument\string} +%D \stoptyping +%D +%D Slower but better: + +{\catcode`.=\@@escape .catcode`.\ 12 .xdef.letterbackslash{.string\}} % hack \def\strippedcsname - {\expandafter\gobbleoneargument\string} + {\expandafter\dostrippedcsname\string} + +\def\dostrippedcsname#1% + {\if\noexpand#1\letterbackslash\else#1\fi} %D \macros %D {savenormalmeaning} diff --git a/tex/context/base/syst-gen.tex b/tex/context/base/syst-gen.tex index eea5351b8..9d4d9fd2e 100644 --- a/tex/context/base/syst-gen.tex +++ b/tex/context/base/syst-gen.tex @@ -346,6 +346,7 @@ \dimendef\!!dimenh=14 %skipdef\!!skipc=4 \dimendef\!!dimeni=16 %skipdef\!!skipd=6 \dimendef\!!dimenj=18 %skipdef\!!skipe=8 + \dimendef\!!dimenk=20 %skipdef\!!skipf=10 \let\!!stringa=\empty \let\!!stringb=\empty \let\!!stringc=\empty \let\!!stringd=\empty \let\!!stringe=\empty \let\!!stringf=\empty @@ -3253,9 +3254,9 @@ \def\p!dogetcommalistsize#1% {\advance\commalistcounter\plusone} -\def\getcommalistsize[#1]% +\def\getcommalistsize#1]% don't loose [{#1}] {\commalistcounter\zerocount - \processcommalist[#1]\p!dogetcommalistsize % was [{#1}] + \processcommalist#1]\p!dogetcommalistsize % was [{#1}] \edef\commalistsize{\the\commalistcounter}} \def\getcommacommandsize[#1]% diff --git a/tex/context/base/syst-tex.tex b/tex/context/base/syst-tex.tex index b439275a4..ddf1d82af 100644 --- a/tex/context/base/syst-tex.tex +++ b/tex/context/base/syst-tex.tex @@ -1,5 +1,5 @@ %D \module -%D [ file=syst-pln, +%D [ file=syst-tex, %D version=1999.03.17, % an oldie: 1995.10.10 %D title=\CONTEXT\ System Macros, %D subtitle=Efficient \PLAIN\ \TEX\ loading, diff --git a/tex/context/base/x-newmml.tex b/tex/context/base/x-newmml.tex index e45f52bc0..32b98525d 100644 --- a/tex/context/base/x-newmml.tex +++ b/tex/context/base/x-newmml.tex @@ -436,11 +436,18 @@ \startsavingXMLelements \rawXMLstacktext\plusone % still on stack, no check, just attr test \stopsavingXMLelements + % http://www.publisherswhodontcareaboutcosts.com/SomeName \doifsetupselse{mmc:csymbol:\XMLpar{csymbol}{definitionURL}{}} { \expanded{\endgroup\noexpand\directsetup{mmc:csymbol:\XMLpar{csymbol}{definitionURL}{}}} } { - \endgroup - \XMLval{mmc:cs}{\XMLop{encoding}}{\firstofoneargument} + % SomeName (fallback) + \splitfilename{\XMLpar{csymbol}{definitionURL}{}} + \doifsetupselse{mmc:csymbol:\splitoffbase} { + \expanded{\endgroup\noexpand\directsetup{mmc:csymbol:\splitoffbase}} + } { + \endgroup + \XMLval{mmc:cs}{\XMLop{encoding}}{\firstofoneargument} + } } \stopsetups @@ -1249,8 +1256,12 @@ \flushXMLstackfrom\plustwo^\prime } } { - \MMLcreset\XMLfirstnamed{apply,ci} - ^{ + \MMLcreset + \XMLfirstnamed{apply,ci} + % there can be problems with nested diff's: ^^{} error + % so we add an empty group here + {}^ + { \XMLdoifonstackelse{degree} { \defXMLfirstnamedtext\ascii{degree} \dorecurse\ascii\prime diff --git a/tex/context/base/xtag-ent.tex b/tex/context/base/xtag-ent.tex index edb437ea5..83f1b1139 100644 --- a/tex/context/base/xtag-ent.tex +++ b/tex/context/base/xtag-ent.tex @@ -123,3 +123,4 @@ \defineXMLentity [dots] {\unknown} \defineXMLentity [amp] {\&} +\defineXMLentity [nbsp] {\nonbreakablespace} diff --git a/tex/context/interface/cont-cz.xml b/tex/context/interface/cont-cz.xml index 1a2417f85..ce881ea6d 100644 --- a/tex/context/interface/cont-cz.xml +++ b/tex/context/interface/cont-cz.xml @@ -6124,7 +6124,9 @@ <cd:constant type="uvolnene"/> <cd:constant type="opakovat"/> <cd:constant type="cd:section"/> + <cd:constant type="odstavec"/> <cd:constant type="dotextu"/> + <cd:constant type="nahodny"/> </cd:keywords> <cd:assignments optional="yes" list="yes"> <cd:parameter name="marginalie"> diff --git a/tex/context/interface/cont-de.xml b/tex/context/interface/cont-de.xml index 14da14a3f..0859070b7 100644 --- a/tex/context/interface/cont-de.xml +++ b/tex/context/interface/cont-de.xml @@ -6124,7 +6124,9 @@ <cd:constant type="lose"/> <cd:constant type="wiederholen"/> <cd:constant type="cd:section"/> + <cd:constant type="absatz"/> <cd:constant type="imtext"/> + <cd:constant type="zufaellig"/> </cd:keywords> <cd:assignments optional="yes" list="yes"> <cd:parameter name="marginalie"> diff --git a/tex/context/interface/cont-en.xml b/tex/context/interface/cont-en.xml index 848ac1dac..f118229aa 100644 --- a/tex/context/interface/cont-en.xml +++ b/tex/context/interface/cont-en.xml @@ -6124,7 +6124,9 @@ <cd:constant type="loose"/> <cd:constant type="repeat"/> <cd:constant type="cd:section"/> + <cd:constant type="paragraph"/> <cd:constant type="intext"/> + <cd:constant type="random"/> </cd:keywords> <cd:assignments optional="yes" list="yes"> <cd:parameter name="margin"> diff --git a/tex/context/interface/cont-fr.xml b/tex/context/interface/cont-fr.xml index 9b494a48a..7e9ad66a9 100644 --- a/tex/context/interface/cont-fr.xml +++ b/tex/context/interface/cont-fr.xml @@ -6124,7 +6124,9 @@ <cd:constant type="perte"/> <cd:constant type="repete"/> <cd:constant type="cd:section"/> + <cd:constant type="paragraphe"/> <cd:constant type="danstexte"/> + <cd:constant type="aleatoire"/> </cd:keywords> <cd:assignments optional="yes" list="yes"> <cd:parameter name="marge"> diff --git a/tex/context/interface/cont-it.xml b/tex/context/interface/cont-it.xml index 709f4acbc..480b6098a 100644 --- a/tex/context/interface/cont-it.xml +++ b/tex/context/interface/cont-it.xml @@ -6124,7 +6124,9 @@ <cd:constant type="lento"/> <cd:constant type="ripeti"/> <cd:constant type="cd:section"/> + <cd:constant type="capoverso"/> <cd:constant type="intesto"/> + <cd:constant type="casuale"/> </cd:keywords> <cd:assignments optional="yes" list="yes"> <cd:parameter name="margine"> diff --git a/tex/context/interface/cont-nl.xml b/tex/context/interface/cont-nl.xml index 1560dd762..e74915152 100644 --- a/tex/context/interface/cont-nl.xml +++ b/tex/context/interface/cont-nl.xml @@ -6124,7 +6124,9 @@ <cd:constant type="los"/> <cd:constant type="herhaal"/> <cd:constant type="cd:section"/> + <cd:constant type="alinea"/> <cd:constant type="intekst"/> + <cd:constant type="willekeurig"/> </cd:keywords> <cd:assignments optional="yes" list="yes"> <cd:parameter name="marge"> diff --git a/tex/context/interface/cont-ro.xml b/tex/context/interface/cont-ro.xml index bc7f41264..5a69366bb 100644 --- a/tex/context/interface/cont-ro.xml +++ b/tex/context/interface/cont-ro.xml @@ -6124,7 +6124,9 @@ <cd:constant type="larg"/> <cd:constant type="repetat"/> <cd:constant type="cd:section"/> + <cd:constant type="paragraf"/> <cd:constant type="intext"/> + <cd:constant type="aleator"/> </cd:keywords> <cd:assignments optional="yes" list="yes"> <cd:parameter name="margine"> |