diff options
77 files changed, 3093 insertions, 288 deletions
diff --git a/doc/context/documents/general/manuals/luatex.pdf b/doc/context/documents/general/manuals/luatex.pdf Binary files differindex 82d0931a9..3af62acd7 100644 --- a/doc/context/documents/general/manuals/luatex.pdf +++ b/doc/context/documents/general/manuals/luatex.pdf diff --git a/doc/context/documents/general/manuals/musings.pdf b/doc/context/documents/general/manuals/musings.pdf Binary files differindex 8c956b7c4..7573569b9 100644 --- a/doc/context/documents/general/manuals/musings.pdf +++ b/doc/context/documents/general/manuals/musings.pdf diff --git a/doc/context/documents/general/qrcs/setup-cs.pdf b/doc/context/documents/general/qrcs/setup-cs.pdf Binary files differindex d1c49f8b1..db96bb54f 100644 --- a/doc/context/documents/general/qrcs/setup-cs.pdf +++ b/doc/context/documents/general/qrcs/setup-cs.pdf diff --git a/doc/context/documents/general/qrcs/setup-de.pdf b/doc/context/documents/general/qrcs/setup-de.pdf Binary files differindex aa6cee0e1..f65a41e0d 100644 --- a/doc/context/documents/general/qrcs/setup-de.pdf +++ b/doc/context/documents/general/qrcs/setup-de.pdf diff --git a/doc/context/documents/general/qrcs/setup-en.pdf b/doc/context/documents/general/qrcs/setup-en.pdf Binary files differindex d8dc51e14..e1e1bc1cd 100644 --- a/doc/context/documents/general/qrcs/setup-en.pdf +++ b/doc/context/documents/general/qrcs/setup-en.pdf diff --git a/doc/context/documents/general/qrcs/setup-fr.pdf b/doc/context/documents/general/qrcs/setup-fr.pdf Binary files differindex 5b4822110..cca294dfd 100644 --- a/doc/context/documents/general/qrcs/setup-fr.pdf +++ b/doc/context/documents/general/qrcs/setup-fr.pdf diff --git a/doc/context/documents/general/qrcs/setup-it.pdf b/doc/context/documents/general/qrcs/setup-it.pdf Binary files differindex 5e7251c8c..789088c63 100644 --- a/doc/context/documents/general/qrcs/setup-it.pdf +++ b/doc/context/documents/general/qrcs/setup-it.pdf diff --git a/doc/context/documents/general/qrcs/setup-mapping-cs.pdf b/doc/context/documents/general/qrcs/setup-mapping-cs.pdf Binary files differindex 9e9c44e8d..7d38dea46 100644 --- a/doc/context/documents/general/qrcs/setup-mapping-cs.pdf +++ b/doc/context/documents/general/qrcs/setup-mapping-cs.pdf diff --git a/doc/context/documents/general/qrcs/setup-mapping-de.pdf b/doc/context/documents/general/qrcs/setup-mapping-de.pdf Binary files differindex 7727c6c80..0fc61cd85 100644 --- a/doc/context/documents/general/qrcs/setup-mapping-de.pdf +++ b/doc/context/documents/general/qrcs/setup-mapping-de.pdf diff --git a/doc/context/documents/general/qrcs/setup-mapping-en.pdf b/doc/context/documents/general/qrcs/setup-mapping-en.pdf Binary files differindex b78b69945..21537aa94 100644 --- a/doc/context/documents/general/qrcs/setup-mapping-en.pdf +++ b/doc/context/documents/general/qrcs/setup-mapping-en.pdf diff --git a/doc/context/documents/general/qrcs/setup-mapping-fr.pdf b/doc/context/documents/general/qrcs/setup-mapping-fr.pdf Binary files differindex afd504957..8ca776be2 100644 --- a/doc/context/documents/general/qrcs/setup-mapping-fr.pdf +++ b/doc/context/documents/general/qrcs/setup-mapping-fr.pdf diff --git a/doc/context/documents/general/qrcs/setup-mapping-it.pdf b/doc/context/documents/general/qrcs/setup-mapping-it.pdf Binary files differindex b530df9c3..a2691c1e8 100644 --- a/doc/context/documents/general/qrcs/setup-mapping-it.pdf +++ b/doc/context/documents/general/qrcs/setup-mapping-it.pdf diff --git a/doc/context/documents/general/qrcs/setup-mapping-nl.pdf b/doc/context/documents/general/qrcs/setup-mapping-nl.pdf Binary files differindex 1d448a5af..4e1491898 100644 --- a/doc/context/documents/general/qrcs/setup-mapping-nl.pdf +++ b/doc/context/documents/general/qrcs/setup-mapping-nl.pdf diff --git a/doc/context/documents/general/qrcs/setup-mapping-ro.pdf b/doc/context/documents/general/qrcs/setup-mapping-ro.pdf Binary files differindex f565c5543..bbd19ee43 100644 --- a/doc/context/documents/general/qrcs/setup-mapping-ro.pdf +++ b/doc/context/documents/general/qrcs/setup-mapping-ro.pdf diff --git a/doc/context/documents/general/qrcs/setup-nl.pdf b/doc/context/documents/general/qrcs/setup-nl.pdf Binary files differindex 304a63658..a1fdf1440 100644 --- a/doc/context/documents/general/qrcs/setup-nl.pdf +++ b/doc/context/documents/general/qrcs/setup-nl.pdf diff --git a/doc/context/documents/general/qrcs/setup-ro.pdf b/doc/context/documents/general/qrcs/setup-ro.pdf Binary files differindex 39ecb74ad..c67652ac4 100644 --- a/doc/context/documents/general/qrcs/setup-ro.pdf +++ b/doc/context/documents/general/qrcs/setup-ro.pdf diff --git a/doc/context/sources/general/manuals/musings/musings-roadmap.tex b/doc/context/sources/general/manuals/musings/musings-roadmap.tex new file mode 100644 index 000000000..f8771ba42 --- /dev/null +++ b/doc/context/sources/general/manuals/musings/musings-roadmap.tex @@ -0,0 +1,372 @@ +% language=uk + +% \showfontkerns + +\startcomponent musings-roadmap + +\environment musings-style + +\startchapter[title={\METATEX, a roadmap}] + +% \startlines \setupalign[flushright] +% Hans Hagen +% Hasselt NL +% September 2018 +% \stoplines + +\startsection[title={Introduction}] + +Here I will shortly wrap up the state of \LUATEX\ and \CONTEXT\ in fall 2018. I +made the first draft of this article as preparation for the \CONTEXT\ meeting +where we also discussed the future. I updated the text afterwards to match the +decisions made there. It's also a personal summary of thoughts and discussions +with team members about where to move next. + +\stopsection + +\startsection[title={The state of affairs}] + +After a dozen years the development of \LUATEX\ has reached a state where adding +more functionality and|/|or opening up more of the internals makes not much +sense. Apart from fixes and maybe some minor extensions, version 1.10 is what you +get. Users can do enough in \LUA\ and there is not much to gain in convenience +and performance. Of course some of the code can and will be cleaned up, as we +still see the effects of going from \PASCAL\ to \CWEB\ to \CCODE. In the process +consistency is on the radar so we might occasionally add a helper. But we also +don't want to move too far away from the original code, which is for instance why +we keep names, keys and other properties found in original \TEX, which in turn +leads to some inconsistencies with extensions added over time. We have to accept +that. + +Because \LUATEX\ development is closely related to \CONTEXT\ development, +especially \MKIV, we've also reached the moment that we can get rid of some older +code and assume the latest \LUATEX\ to be used. Because we do so much in \LUA\ +the question is always to what extent the benefits outweigh the drawbacks. Just +in case you wonder why we use \LUA\ extensively, the main reason is that it is +easier and more efficient to manage data in this language and modern typesetting +needs much data. It also permits us to extend regular \TEX\ functionality. But, +one should not overrate the impact: we still let \TEX\ do what \TEX\ is best at! + +Performance is quite important. It doesn't make sense to create a powerful +typesetting system where processing a page takes a second. We have discussed +performance before since one of the complaints about \LUATEX\ is that it is slow. +A simple, basic test is this: + +\starttyping +\starttext + \dorecurse{1000}{\input tufte \par} +\stoptext +\stoptyping + +This involves 1000 times loading a file (and reporting that on the console, which +can influence runtime), typesetting paragraphs, splitting of a page and of course +loading fonts and saving to the \PDF\ file. When I run this on a modest machine, +I get these (relative) timings for the (about) 225 pages: + +\starttabulate[|l|c|c|c|c|] +\BC \TEX\ engine used \BC \PDFTEX \BC \LUATEX \BC \LUAJITTEX \BC \XETEX \NC \NR +\BC runtime in seconds \NC 2.0 \NC 3.9 \NC 3.0 \NC 8.4 \NC \NR +\stoptabulate + +Now, as expected the 8 bit \PDFTEX\ is the winner here but \LUATEX\ is not doing +that bad. I don't know why \XETEX\ is so much slower, maybe because its 64 bit +binary is less optimal. I once noticed that a 64 bit \PDFTEX\ performed worse on +such a test than \LUATEX, for which I always use 64 bit binaries. + +If you consider that often much more is done than in this example, you can take +my word that \LUATEX\ quickly outpaces \PDFTEX\ on more complex tasks. In that +sense it is now our benchmark. It must be said that the \MKIV\ code is probably a +bit more efficient than the \MKII\ code but that doesn't matter much in this +simple test because hardly any macro magic happens here; it mostly tests basic +font processing, paragraph building and page construction. I don't think that I +can squeeze out more pages per second, at least not without users telling me +where they encounter bottlenecks that don't result from their style coding. It's +no problem to write inefficient macros (or styles) so normally a user should +first carefully check her|/|his own work. Using a more modern \CPU\ with proper +caching and an \SSD\ helps too. + +So, to summarize, we can say that with version 1.10 \LUATEX\ is sort of finished. +Our mission is now to make \LUATEX\ robust and stable. Things can be added and +improved, but these are small and mostly consistency related. + +\stopsection + +\startsection[title={More in \LUA}] + +Till now I always managed to add functionality to \CONTEXT\ without hampering +performance too much. Of course the biggest challenge is always in handling fonts +and common features like color because that all happens in \LUA. So, the question +is, what if we delegate more of the core functionality to \LUA ? I will discuss a +few options because the \CONTEXT\ developers and users need to agree on the path +to follow. One question there is, are the possible performance hits (which can be +an inconvenience) compensated by better and easier typesetting. + +Fonts, colors, special typesetting features like spaced kerning, protrusion, +expansion, but also dropped caps, line numbering, marginal notes, tables, +structure related things, floats and spacing are not open for much discussion. +All the things that happen in \LUA\ combined with macros is there and will stay. +But how about hyphenation, paragraph building and page building? And how about a +leaner and meaner, future safe engine? + +Hyphenation is handled in the \TEX\ core. But in \CONTEXT\ already for years one +can also use a \LUA\ based variant. There is room for extensions and improvements +there. Interesting is that performance is more or less the same, so this is an +area where we might switch to the \LUA\ method eventually. It compares to fonts, +where node mode is more or less the standard and base mode the old way. + +Building the paragraphs in \LUA\ is also available in \MKIV, although it needs an +update. Again performance is not that bad, so when we add features not possible +(or hard to do) in regular \TEX, it might actually pay of to default to the +par builder written in \LUA. + +The page builder is also doable in \LUA\ but so far I only played a bit with a +\LUA\ based variant. I might pick up that thread. However, when we would switch to +\LUA\ there, it might have a bit of a penalty, unless we combine it with some +other mechanisms which is not entirely trivial, as it would mean a diversion from +the way \TEX\ does it normally. + +How about math? We could at some point do math rendering in \LUA\ but because the +core mechanism is the standard, it doesn't really makes much sense. It would also +touch the soul of \TEX. But, I might give it a try, just for fun, so that I can +play with it a bit. It's typically something for cold and rainy days with some +music in the background. + +We already use \LUA\ in the frontend: locating and reading files in \TEX, +\XML, \LUA\ and whatever input format. Normalization and manipulation is all +active and available. The backend is also depending on \LUA, like support for +special \PDF\ features and exporting to \XML . The engine still handles the page +stream conversion, font inclusion and object management. + +The inclusion of images is also handled by the engine, although in \CONTEXT\ we +can delegate \PDF\ inclusion to \LUA. Interesting is that this has no performance +hit. + +With some juggling the page stream conversion can also be done in \LUA, and I +might move that code into the \CONTEXT\ distribution. Here we do have a +performance hit: about one second more runtime on the 14 seconds needed for the +300 page \LUATEX\ manual and just over more than half a second on a 11 second +\LUAJITTEX\ run. The manual has lots of tables, verbatim, indices and uses color +as well as a more than average number of fonts and much time is spent in \LUA. So +there is a price to pay there. I tried to speed that up but there is not much to +gain there. + +So, say that we default to \LUA\ based hyphenation, which enables some new +functionality, \LUA\ based par building, which permits some heuristics for corner +cases, and \LUA\ based page building, which might result in more control over +tricky cases. A total performance hit of some 5\% is probably acceptable, +especially because by that time I might have replaced my laptop and won't notice +the degrade. This still fits in the normal progress and doesn't really demand a +roadmap or wider acceptance. And of course we would still use the same strategies +as implemented in traditional \TEX\ as default anyway. + +\stopsection + +\startsection[title={A more drastic move}] + +More fundamental is the question whether we delegate more backend activity to +\LUA\ code. If we decide to handle the page stream in \LUA, then the next +question is, why not also delegate object management and font inclusion to +\LUA. Now, keep in mind that this is all very \CONTEXT\ specific! Already for +more than a decade we delegate a lot to \LUA, and also we have a rather tight +control over this core functionality. This would mean that \CONTEXT\ doesn't +really need the backend code in the engine. \footnote {For generic packages like +TikZ we (can) provide some primitive emulators, which is rather trivial to +implement.} + +That situation is actually not unique. For instance, already for a while we don't +need the \LUATEX\ font loader either, as loading the \OPENTYPE\ files is done in +\LUA. So, we could also get rid of the font loader code. Currently some code is +shared with the font inclusion in the backend but that can be isolated. + +You can see a \TEX\ engine as being made from several parts, but the core really +concerns only two processes: reading, storing and expanding macros on the one +hand, and converting a stream of characters into lines, paragraphs, pages etc. +Fonts are mostly an abstraction: they are visible in so called glyph nodes as +font identifier (a number) and character code (also a number) properties. The +result, nowadays being \PDF, is also an abstraction: at some point the engine +converts the to be shipped out box in \PDF\ instructions, and in our case, +relatively simple ones. The backend registers which characters and fonts are used +and also includes the right resources. But, the backend is not part of the core +as such! It has been introduced in \PDFTEX\ and is a so called extension. + +So, what does that all mean for a future version of \CONTEXT\ and \LUATEX ? It +means that we can decide to follow up with a \CONTEXT\ that does more in \LUA, +which means not hard coded in a binary, on the one hand, but that we can also +decide to strip the engine from non|-|core code. But, given that \LUATEX\ is also +used in other macro packages, this would mean a different engine. We cannot say +that \LUATEX\ is stable when we also experiment with core components. + +We've seen folks picking up experimental versions assuming that it is a precursor +to official code. So, in order to move on we need to avoid confusion: we need to +use another name. Choosing a name is always tricky but as Taco already registered +the \METATEX\ domain, and because in the \CONTEXT\ distribution you will find +references to \METATEX, we will use that name for the future engine. Adding \LUA\ +to that name makes sense but then the name would become too long. + +The main difference between \METATEX\ and \LUATEX\ would be that the former has +no file lookup library, no hardcoded font loader, and no backend generator (but +possibly some helpers, and these need time to evolve). We're basically back where +\TEX\ started but instead of coding these extensions in \PASCAL\ or \CCODE\ we +use \LUA. We're also kind of back to when we first started experimenting with +\LUATEX\ in \CONTEXT\ where test, write and rewrite were going in parallel. But, +as said, we cannot impose that on a wide audience. + +If we go for such a lean and mean follow up, then we can also do a more drastic +cleanup of obsolete code in \CONTEXT\ (dating from \ETEX, \PDFTEX, \ALEPH, etc.). +We then are sort of back to where it all started: we go back to the basics. This +might mean dropping some primitives (one can define them as dummy). Of course we +could generalize some of the \CONTEXT\ code to provide the kicked out +functionality but would that pay of? Probably not. + +Just for the record: replacing the handling of macros, registers, grouping, etc.\ +to \LUA\ is not really an option as the performance hit would make a large system +like \CONTEXT\ sort of unusable: it's no option and not even considered (although +I must admit that I have some experimental \LUA\ based \TEX\ parser code around). + +It is quite likely that building \METATEX\ from source for the moment will be an +option to the build script. But we can also decide to simplify that process, +which is possible because we only need one binary. But in general we can assume +that one can generate \METATEX\ and \LUATEX\ from the same source. A first step +probably is a further isolation of the backend code. The fontloader and file +handling code already can be made optional. + +Given that we only need one binary (it being \LUATEX\ or \METATEX) and nowadays +only use \OPENTYPE\ fonts, one can even start thinking of a mini distribution, +possibly with a zipped resource tree, something we experimented with in the early +days of \LUATEX. + +Another though I have been playing with is a better separation between low level +and high level \CONTEXT\ commands, and whether the low level layer should be more +generic in nature (so that one can run specific packages on top of it instead of +the whole of \CONTEXT) but that might not be worth the trouble. + +\stopsection + +\startsection[title={Interlude}] + +If we look at the future, it's good to also look at the past. Opening up \TEX\ +the way we did has many advantages but also potential drawbacks. It works quite +well in \CONTEXT\ because we ship an integrated package. I don't think that there +are many users who kick in their own callbacks. It is possible but completely up +to the user to make sure things work out well. Performance hits, interference, +crashes: those who interfere with the internals can sort that out themselves. I'm +not sure how well that works out in other macro packages but it is a time bomb if +users start doing that. Of course the documented interfaces to use \LUA\ in +\CONTEXT\ are supported. So far I think we're not yet bitten in the tail. We keep +this aspect out of the discussion. + +Another important aspect is stability of the engine. Sometimes we get suggestions +for changes or patches that works for a specific case but for sure will have side +effects on \CONTEXT. Just as we don't test \LATEX\ side effects, \LATEX\ users +don't check \CONTEXT. And we're not even talking of users who expect their code +to keep working. A tight control over the source is important but cannot be we +will not be around for ever. This means that at some point \LUATEX\ should not be +changed any more, even when we observe side effects we want to get rid of, +because these side effects can be in use. This is another argument for a stripped +down engine. The less there is to mess with, the less the mess. + +\stopsection + +\startsection[title={Audience}] + +So how about \CONTEXT\ itself? Of course we can make it better. We can add more +examples and more documentation. We can try to improve support. The main question +for us (as developers) is who actually is our audience. From the mails coming to +the \CONTEXT\ support list it looks like a rather diverse group of users. + +At \TEX\ meetings there are often discussions about promoting \TEX. I can agree +on the fact that even for simple documents it makes a lot of sense to use \TEX, +but who will take the first hurdles? How many people really produce a lot of +documents? And how many need \TEX\ after maybe a short period of (enforced) usage +at the university? + +It's not trivial to recognize the possibilities and power of the +\LUATEX|-|\CONTEXT\ combination. We never got any serious requests for support +from large organizations. In fact, we do use this combination in a few projects +for educational publishers, but there it's actually the authors and editors doing +the work. It's seldom company policy to use tools that efficiently automate +typesetting. I dare to say that publishers are not really an audience at all: +they normally delegate the task. They might accept \TEX\ documents but let them +rekey or adapt far|-|far|-|away and as cheap as possible. Thinking of it, the +main reason for Don Knuth for writing \TEX\ in the first place was the ability to +control the look and feel and quality. It were developments at typesetters and +publishers that triggered development of \TEX . It was user demand. And the +success of \TEX\ was largely due to the unique personality and competence of the +author. + +System integrators qualify as audience but I fear that \TEX\ is not considered +hip and modern. It doesn't seem to matter if you can demonstrate that it can do a +wonderful job efficiently and relatively cheap. Also the fact that an +installation can be very stable on the long run is of no importance. Maybe that +audience (market place) is all about \quotation {The more we have to program and +update regularly, the merrier.}. Marketing \TEX\ is difficult. + +Those who render multiple products, maintain manuals, have to render many +documents automatically qualify as audience. But often company policies, +preferred suppliers, so called standard tools etc.\ are used as argument against +\TEX. It's a missed opportunity. + +One needs a certain mindset to recognize the potential and the question is, how +do we reach that audience. Drawing a roadmap for that is not easy but worth +discussing. We're open for suggestions. + +% \footnote {It's kind of interesting that recently the \TEX\ User Group announced +% its presence on Facebook and Twitter. Apart from wondering how that gets updated, +% one can also wonder how many potential (or even current) users go there, given +% that these platforms are subjected to rise and fall. I'm on neither of them and +% don't plan to. Kids (our future users) that I know already said goodbye to them. +% We'll see how that works out.} + +\stopsection + +\startsection[title={Conclusion}] + +At the \CONTEXT\ user meeting those present agreed that moving forward this way +makes sense. This means that we will explore a lean and mean \METATEX\ alongside +\LUATEX. There is no rush and it's all volunteer work so we will take our time +for this. It boils down to some reshuffling of code so that we can remove the +built|-|in font loader, file handling, and probably also \SYNCTEX\ because we can +emulate that. Then the backend with its font inclusion code will be cleaned up a +bit (we even discussed only supporting modern wide fonts). It's no big deal to +adapt \CONTEXT\ to this (so it can and will support both \LUATEX\ and \METATEX). +Eventually the backend might go away but now we're talking years ahead. By then +we can also explore the option to make \METATEX\ start out as a \LUA\ function +call (the main control loop) and become reentrant. There will probably not be +many changes to the opened up \TEX\ kernel, but we might extend the \METAPOST\ +part a bit (some of that was discussed at the meeting) especially because it is a +nice tool to visualize big data. + +As with \LUATEX\ development we will go in small steps so that we keep a working +system. Of course \LUATEX\ is always there as stable fallback. The experiments +will mostly happen in the experimental branch and binaries will be generated +using the compile farm on the \CONTEXT\ garden, just as happens now. This also +limits testing and exploring to the \CONTEXT\ community so that there are no side +effects for mainstream \LUATEX\ usage. + +Nowadays, instead if roadmaps, we tend to use navigational gadgets that adapt +themselves to the situation. On the road by car this can mean a detour and when +walking around it can be going to suggested points of interest. During the +excursion at the meeting, we noticed that after the drivers (navigators) +synchronized their gadget with Jano, the routes that were followed differed a +bit. We saw cars in front of going a different direction and cars behind us +arriving from a different direction. So, even when we talk about roadmaps, our +route can be adapted to the situation. + +Now here is something to think about. If you look at the \TEX\ community you will +notice that it's an aging community. User groups seem to loose members, although +the \CONTEXT\ group is currently still growing. Fortunately we see a new +generation taking interest and the \CONTEXT\ users are a pleasant mix and it +makes me stay around. I see it as an \quote {old timers} responsibility to have +\TEX\ and its environment in a healthy state by the time I retire from it +(although I have no plans in that direction). In parallel to the upcoming +development I think we will also see a change in \TEX\ use and usage. This aspect +was also discussed at the meeting and for sure will get a follow up on the +mailing lists and future meetings. It might as well influence the decisions we +make the upcoming years. So far \TEX\ has never failed us in it's flexibility and +capacity to adapt, so let's end on that positive note. + +\stopsection + +\stopchapter + +\stopcomponent diff --git a/doc/context/sources/general/manuals/musings/musings.tex b/doc/context/sources/general/manuals/musings/musings.tex index a49de9265..e2787dc99 100644 --- a/doc/context/sources/general/manuals/musings/musings.tex +++ b/doc/context/sources/general/manuals/musings/musings.tex @@ -15,7 +15,7 @@ \component musings-whytex \component musings-staygo \component musings-stability - % \component musings-roadmap + \component musings-roadmap \stopbodymatter \stopproduct diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index 60ca9a337..c45ed26ca 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -3461,7 +3461,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-number"] = package.loaded["l-number"] or true --- original size: 5645, stripped down to: 2253 +-- original size: 5713, stripped down to: 2304 if not modules then modules={} end modules ['l-number']={ version=1.001, @@ -3572,6 +3572,9 @@ function number.decimaltobyte(d) return b end end +function number.idiv(i,d) + return floor(i/d) +end end -- of closure @@ -8064,7 +8067,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-sac"] = package.loaded["util-sac"] or true --- original size: 9987, stripped down to: 7878 +-- original size: 11000, stripped down to: 8650 if not modules then modules={} end modules ['util-sac']={ version=1.001, @@ -8082,6 +8085,9 @@ function streams.open(filename,zerobased) local f=io.loaddata(filename) return { f,1,#f,zerobased or false } end +function streams.openstring(f,zerobased) + return { f,1,#f,zerobased or false } +end function streams.close() end function streams.size(f) @@ -8398,19 +8404,49 @@ if sio and sio.readcardinal2 then streams.readinteger=streams.readinteger1 end if sio and sio.readcardinaltable then - streams.readcardinaltable=sio.readcardinaltable - streams.readintegertable=sio.readintegertable + local readcardinaltable=sio.readcardinaltable + local readintegertable=sio.readintegertable + function utilities.streams.readcardinaltable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end + return readcardinaltable(f[1],i,n,b) + end + function utilities.streams.readintegertable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end + return readintegertable(f[1],i,n,b) + end else local readcardinal1=streams.readcardinal1 local readcardinal2=streams.readcardinal2 local readcardinal3=streams.readcardinal3 local readcardinal4=streams.readcardinal4 function streams.readcardinaltable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end local t={} - if b==1 then for i=1,n do t[i]=readcardinal1(f) end - elseif b==2 then for i=1,n do t[i]=readcardinal2(f) end - elseif b==3 then for i=1,n do t[i]=readcardinal3(f) end - elseif b==4 then for i=1,n do t[i]=readcardinal4(f) end end + if b==1 then for i=1,n do t[i]=readcardinal1(f[1],i) end + elseif b==2 then for i=1,n do t[i]=readcardinal2(f[1],i) end + elseif b==3 then for i=1,n do t[i]=readcardinal3(f[1],i) end + elseif b==4 then for i=1,n do t[i]=readcardinal4(f[1],i) end end return t end local readinteger1=streams.readinteger1 @@ -8418,11 +8454,19 @@ else local readinteger3=streams.readinteger3 local readinteger4=streams.readinteger4 function streams.readintegertable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end local t={} - if b==1 then for i=1,n do t[i]=readinteger1(f) end - elseif b==2 then for i=1,n do t[i]=readinteger2(f) end - elseif b==3 then for i=1,n do t[i]=readinteger3(f) end - elseif b==4 then for i=1,n do t[i]=readinteger4(f) end end + if b==1 then for i=1,n do t[i]=readinteger1(f[1],i) end + elseif b==2 then for i=1,n do t[i]=readinteger2(f[1],i) end + elseif b==3 then for i=1,n do t[i]=readinteger3(f[1],i) end + elseif b==4 then for i=1,n do t[i]=readinteger4(f[1],i) end end return t end end @@ -24622,8 +24666,8 @@ end -- of closure -- used libraries : l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 984519 --- stripped bytes : 348231 +-- original bytes : 985600 +-- stripped bytes : 348489 -- end library merge diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua index 60ca9a337..c45ed26ca 100644 --- a/scripts/context/stubs/mswin/mtxrun.lua +++ b/scripts/context/stubs/mswin/mtxrun.lua @@ -3461,7 +3461,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-number"] = package.loaded["l-number"] or true --- original size: 5645, stripped down to: 2253 +-- original size: 5713, stripped down to: 2304 if not modules then modules={} end modules ['l-number']={ version=1.001, @@ -3572,6 +3572,9 @@ function number.decimaltobyte(d) return b end end +function number.idiv(i,d) + return floor(i/d) +end end -- of closure @@ -8064,7 +8067,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-sac"] = package.loaded["util-sac"] or true --- original size: 9987, stripped down to: 7878 +-- original size: 11000, stripped down to: 8650 if not modules then modules={} end modules ['util-sac']={ version=1.001, @@ -8082,6 +8085,9 @@ function streams.open(filename,zerobased) local f=io.loaddata(filename) return { f,1,#f,zerobased or false } end +function streams.openstring(f,zerobased) + return { f,1,#f,zerobased or false } +end function streams.close() end function streams.size(f) @@ -8398,19 +8404,49 @@ if sio and sio.readcardinal2 then streams.readinteger=streams.readinteger1 end if sio and sio.readcardinaltable then - streams.readcardinaltable=sio.readcardinaltable - streams.readintegertable=sio.readintegertable + local readcardinaltable=sio.readcardinaltable + local readintegertable=sio.readintegertable + function utilities.streams.readcardinaltable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end + return readcardinaltable(f[1],i,n,b) + end + function utilities.streams.readintegertable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end + return readintegertable(f[1],i,n,b) + end else local readcardinal1=streams.readcardinal1 local readcardinal2=streams.readcardinal2 local readcardinal3=streams.readcardinal3 local readcardinal4=streams.readcardinal4 function streams.readcardinaltable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end local t={} - if b==1 then for i=1,n do t[i]=readcardinal1(f) end - elseif b==2 then for i=1,n do t[i]=readcardinal2(f) end - elseif b==3 then for i=1,n do t[i]=readcardinal3(f) end - elseif b==4 then for i=1,n do t[i]=readcardinal4(f) end end + if b==1 then for i=1,n do t[i]=readcardinal1(f[1],i) end + elseif b==2 then for i=1,n do t[i]=readcardinal2(f[1],i) end + elseif b==3 then for i=1,n do t[i]=readcardinal3(f[1],i) end + elseif b==4 then for i=1,n do t[i]=readcardinal4(f[1],i) end end return t end local readinteger1=streams.readinteger1 @@ -8418,11 +8454,19 @@ else local readinteger3=streams.readinteger3 local readinteger4=streams.readinteger4 function streams.readintegertable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end local t={} - if b==1 then for i=1,n do t[i]=readinteger1(f) end - elseif b==2 then for i=1,n do t[i]=readinteger2(f) end - elseif b==3 then for i=1,n do t[i]=readinteger3(f) end - elseif b==4 then for i=1,n do t[i]=readinteger4(f) end end + if b==1 then for i=1,n do t[i]=readinteger1(f[1],i) end + elseif b==2 then for i=1,n do t[i]=readinteger2(f[1],i) end + elseif b==3 then for i=1,n do t[i]=readinteger3(f[1],i) end + elseif b==4 then for i=1,n do t[i]=readinteger4(f[1],i) end end return t end end @@ -24622,8 +24666,8 @@ end -- of closure -- used libraries : l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 984519 --- stripped bytes : 348231 +-- original bytes : 985600 +-- stripped bytes : 348489 -- end library merge diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun index 60ca9a337..c45ed26ca 100644 --- a/scripts/context/stubs/unix/mtxrun +++ b/scripts/context/stubs/unix/mtxrun @@ -3461,7 +3461,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-number"] = package.loaded["l-number"] or true --- original size: 5645, stripped down to: 2253 +-- original size: 5713, stripped down to: 2304 if not modules then modules={} end modules ['l-number']={ version=1.001, @@ -3572,6 +3572,9 @@ function number.decimaltobyte(d) return b end end +function number.idiv(i,d) + return floor(i/d) +end end -- of closure @@ -8064,7 +8067,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-sac"] = package.loaded["util-sac"] or true --- original size: 9987, stripped down to: 7878 +-- original size: 11000, stripped down to: 8650 if not modules then modules={} end modules ['util-sac']={ version=1.001, @@ -8082,6 +8085,9 @@ function streams.open(filename,zerobased) local f=io.loaddata(filename) return { f,1,#f,zerobased or false } end +function streams.openstring(f,zerobased) + return { f,1,#f,zerobased or false } +end function streams.close() end function streams.size(f) @@ -8398,19 +8404,49 @@ if sio and sio.readcardinal2 then streams.readinteger=streams.readinteger1 end if sio and sio.readcardinaltable then - streams.readcardinaltable=sio.readcardinaltable - streams.readintegertable=sio.readintegertable + local readcardinaltable=sio.readcardinaltable + local readintegertable=sio.readintegertable + function utilities.streams.readcardinaltable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end + return readcardinaltable(f[1],i,n,b) + end + function utilities.streams.readintegertable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end + return readintegertable(f[1],i,n,b) + end else local readcardinal1=streams.readcardinal1 local readcardinal2=streams.readcardinal2 local readcardinal3=streams.readcardinal3 local readcardinal4=streams.readcardinal4 function streams.readcardinaltable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end local t={} - if b==1 then for i=1,n do t[i]=readcardinal1(f) end - elseif b==2 then for i=1,n do t[i]=readcardinal2(f) end - elseif b==3 then for i=1,n do t[i]=readcardinal3(f) end - elseif b==4 then for i=1,n do t[i]=readcardinal4(f) end end + if b==1 then for i=1,n do t[i]=readcardinal1(f[1],i) end + elseif b==2 then for i=1,n do t[i]=readcardinal2(f[1],i) end + elseif b==3 then for i=1,n do t[i]=readcardinal3(f[1],i) end + elseif b==4 then for i=1,n do t[i]=readcardinal4(f[1],i) end end return t end local readinteger1=streams.readinteger1 @@ -8418,11 +8454,19 @@ else local readinteger3=streams.readinteger3 local readinteger4=streams.readinteger4 function streams.readintegertable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end local t={} - if b==1 then for i=1,n do t[i]=readinteger1(f) end - elseif b==2 then for i=1,n do t[i]=readinteger2(f) end - elseif b==3 then for i=1,n do t[i]=readinteger3(f) end - elseif b==4 then for i=1,n do t[i]=readinteger4(f) end end + if b==1 then for i=1,n do t[i]=readinteger1(f[1],i) end + elseif b==2 then for i=1,n do t[i]=readinteger2(f[1],i) end + elseif b==3 then for i=1,n do t[i]=readinteger3(f[1],i) end + elseif b==4 then for i=1,n do t[i]=readinteger4(f[1],i) end end return t end end @@ -24622,8 +24666,8 @@ end -- of closure -- used libraries : l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 984519 --- stripped bytes : 348231 +-- original bytes : 985600 +-- stripped bytes : 348489 -- end library merge diff --git a/scripts/context/stubs/win64/mtxrun.lua b/scripts/context/stubs/win64/mtxrun.lua index 60ca9a337..c45ed26ca 100644 --- a/scripts/context/stubs/win64/mtxrun.lua +++ b/scripts/context/stubs/win64/mtxrun.lua @@ -3461,7 +3461,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-number"] = package.loaded["l-number"] or true --- original size: 5645, stripped down to: 2253 +-- original size: 5713, stripped down to: 2304 if not modules then modules={} end modules ['l-number']={ version=1.001, @@ -3572,6 +3572,9 @@ function number.decimaltobyte(d) return b end end +function number.idiv(i,d) + return floor(i/d) +end end -- of closure @@ -8064,7 +8067,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-sac"] = package.loaded["util-sac"] or true --- original size: 9987, stripped down to: 7878 +-- original size: 11000, stripped down to: 8650 if not modules then modules={} end modules ['util-sac']={ version=1.001, @@ -8082,6 +8085,9 @@ function streams.open(filename,zerobased) local f=io.loaddata(filename) return { f,1,#f,zerobased or false } end +function streams.openstring(f,zerobased) + return { f,1,#f,zerobased or false } +end function streams.close() end function streams.size(f) @@ -8398,19 +8404,49 @@ if sio and sio.readcardinal2 then streams.readinteger=streams.readinteger1 end if sio and sio.readcardinaltable then - streams.readcardinaltable=sio.readcardinaltable - streams.readintegertable=sio.readintegertable + local readcardinaltable=sio.readcardinaltable + local readintegertable=sio.readintegertable + function utilities.streams.readcardinaltable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end + return readcardinaltable(f[1],i,n,b) + end + function utilities.streams.readintegertable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end + return readintegertable(f[1],i,n,b) + end else local readcardinal1=streams.readcardinal1 local readcardinal2=streams.readcardinal2 local readcardinal3=streams.readcardinal3 local readcardinal4=streams.readcardinal4 function streams.readcardinaltable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end local t={} - if b==1 then for i=1,n do t[i]=readcardinal1(f) end - elseif b==2 then for i=1,n do t[i]=readcardinal2(f) end - elseif b==3 then for i=1,n do t[i]=readcardinal3(f) end - elseif b==4 then for i=1,n do t[i]=readcardinal4(f) end end + if b==1 then for i=1,n do t[i]=readcardinal1(f[1],i) end + elseif b==2 then for i=1,n do t[i]=readcardinal2(f[1],i) end + elseif b==3 then for i=1,n do t[i]=readcardinal3(f[1],i) end + elseif b==4 then for i=1,n do t[i]=readcardinal4(f[1],i) end end return t end local readinteger1=streams.readinteger1 @@ -8418,11 +8454,19 @@ else local readinteger3=streams.readinteger3 local readinteger4=streams.readinteger4 function streams.readintegertable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end local t={} - if b==1 then for i=1,n do t[i]=readinteger1(f) end - elseif b==2 then for i=1,n do t[i]=readinteger2(f) end - elseif b==3 then for i=1,n do t[i]=readinteger3(f) end - elseif b==4 then for i=1,n do t[i]=readinteger4(f) end end + if b==1 then for i=1,n do t[i]=readinteger1(f[1],i) end + elseif b==2 then for i=1,n do t[i]=readinteger2(f[1],i) end + elseif b==3 then for i=1,n do t[i]=readinteger3(f[1],i) end + elseif b==4 then for i=1,n do t[i]=readinteger4(f[1],i) end end return t end end @@ -24622,8 +24666,8 @@ end -- of closure -- used libraries : l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 984519 --- stripped bytes : 348231 +-- original bytes : 985600 +-- stripped bytes : 348489 -- end library merge diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 439cdf147..72d476f01 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2018.10.08 17:44} +\newcontextversion{2018.10.17 15:06} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index 88a4cac8c..922f96320 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2018.10.08 17:44} +\edef\contextversion{2018.10.17 15:06} %D For those who want to use this: diff --git a/tex/context/base/mkii/mult-fr.mkii b/tex/context/base/mkii/mult-fr.mkii index 5c94eaf24..69804afcb 100644 --- a/tex/context/base/mkii/mult-fr.mkii +++ b/tex/context/base/mkii/mult-fr.mkii @@ -1241,6 +1241,7 @@ \setinterfaceconstant{textstyle}{styletexte} \setinterfaceconstant{textwidth}{largeurtexte} \setinterfaceconstant{threshold}{threshold} +\setinterfaceconstant{time}{time} \setinterfaceconstant{title}{titre} \setinterfaceconstant{titlecolor}{couleurtitre} \setinterfaceconstant{titlecommand}{titlecommand} diff --git a/tex/context/base/mkiv/back-pdf.mkiv b/tex/context/base/mkiv/back-pdf.mkiv index 365493fff..799df2538 100644 --- a/tex/context/base/mkiv/back-pdf.mkiv +++ b/tex/context/base/mkiv/back-pdf.mkiv @@ -37,6 +37,7 @@ \registerctxluafile{lpdf-epd}{} \else \registerctxluafile{lpdf-pde}{} + \registerctxluafile{lpdf-img}{optimize} \fi \registerctxluafile{lpdf-epa}{} diff --git a/tex/context/base/mkiv/bibl-tra.mkiv b/tex/context/base/mkiv/bibl-tra.mkiv index 3ff07ead5..5389400f3 100644 --- a/tex/context/base/mkiv/bibl-tra.mkiv +++ b/tex/context/base/mkiv/bibl-tra.mkiv @@ -1500,7 +1500,7 @@ \c!numbercommand=\bibleftnumber] \unexpanded\def\preloadbiblist - {\globallet\preloadbiblist\relax + {\glet\preloadbiblist\relax \dousepublications\jobname} % \appendtoks \preloadbiblist \to \everysetuppublications diff --git a/tex/context/base/mkiv/cldf-ini.mkiv b/tex/context/base/mkiv/cldf-ini.mkiv index 67eea6892..29fb15d68 100644 --- a/tex/context/base/mkiv/cldf-ini.mkiv +++ b/tex/context/base/mkiv/cldf-ini.mkiv @@ -47,8 +47,8 @@ % \catcode`=\activecatcode \let\luafunction % saves 10% on the call -% \catcodetable\ctxcatcodes \catcode`^=\superscriptcatcode\catcode1=\activecatcode \global\let^^A=\cldf -% \catcodetable\ctxcatcodes \catcode`^=\superscriptcatcode\catcode2=\activecatcode \global\let^^B=\cldn +% \catcodetable\ctxcatcodes \catcode`^=\superscriptcatcode\catcode1=\activecatcode \glet^^A=\cldf +% \catcodetable\ctxcatcodes \catcode`^=\superscriptcatcode\catcode2=\activecatcode \glet^^B=\cldn \normalprotected\def\cldprocessfile#1{\directlua{context.runfile("#1")}} \def\cldloadfile #1{\directlua{context.loadfile("#1")}} diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index c3c035160..5ce172570 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2018.10.08 17:44} +\newcontextversion{2018.10.17 15:06} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 9b166fb03..8b144d609 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -42,7 +42,7 @@ %D has to match \type {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2018.10.08 17:44} +\edef\contextversion{2018.10.17 15:06} \edef\contextkind {beta} %D For those who want to use this: diff --git a/tex/context/base/mkiv/font-con.lua b/tex/context/base/mkiv/font-con.lua index 54cf2c199..d238084d0 100644 --- a/tex/context/base/mkiv/font-con.lua +++ b/tex/context/base/mkiv/font-con.lua @@ -739,6 +739,8 @@ function constructors.scale(tfmdata,specification) chr.tounicode = tounicode(isunicode) -- in luatex > 0.85 we can do this: -- chr.tounicode = isunicode + else +-- chr.tounicode = "FFFD" end if hasquality then -- we could move these calculations elsewhere (saves calculations) diff --git a/tex/context/base/mkiv/font-imp-quality.lua b/tex/context/base/mkiv/font-imp-quality.lua index 52eed080c..bb78d9435 100644 --- a/tex/context/base/mkiv/font-imp-quality.lua +++ b/tex/context/base/mkiv/font-imp-quality.lua @@ -343,8 +343,7 @@ local function map_opbd_onto_protrusion(tfmdata,value,opbd) if v == true then -- zero else - -- local p = - v[3] / descriptions[k].width-- or 1 ~= 0 too but the same - local p = - (v[1] / 1000) * factor * left + local p = - (v[3] / 1000) * factor * left characters[k].left_protruding = p if trace_protrusion then report_protrusions("lfbd -> %C -> %p",k,p) @@ -376,8 +375,7 @@ local function map_opbd_onto_protrusion(tfmdata,value,opbd) if v == true then -- zero else - -- local p = v[3] / descriptions[k].width -- or 3 - local p = (v[1] / 1000) * factor * right + local p = (v[1] / 1000) * factor * right -- or [3] ? characters[k].right_protruding = p if trace_protrusion then report_protrusions("rtbd -> %C -> %p",k,p) diff --git a/tex/context/base/mkiv/font-otc.lua b/tex/context/base/mkiv/font-otc.lua index c2e89599a..595778e34 100644 --- a/tex/context/base/mkiv/font-otc.lua +++ b/tex/context/base/mkiv/font-otc.lua @@ -7,7 +7,7 @@ if not modules then modules = { } end modules ['font-otc'] = { } local insert, sortedkeys, sortedhash, tohash = table.insert, table.sortedkeys, table.sortedhash, table.tohash -local type, next = type, next +local type, next, tonumber = type, next, tonumber local lpegmatch = lpeg.match local utfbyte, utflen = utf.byte, utf.len local sortedhash = table.sortedhash @@ -174,6 +174,10 @@ local function addfeature(data,feature,specifications) return end + local p = lpeg.P("P") + * (lpeg.patterns.hexdigit^1/function(s) return tonumber(s,16) end) + * lpeg.P(-1) + local function tounicode(code) if not code then return @@ -183,6 +187,7 @@ local function addfeature(data,feature,specifications) end local u = unicodes[code] if u then + -- unicodes[code] = u return u end if utflen(code) == 1 then @@ -191,10 +196,19 @@ local function addfeature(data,feature,specifications) return u end end + local u = lpegmatch(p,code) + if u then + -- unicodes[code] = u + return u + end if not aglunicodes then aglunicodes = fonts.encodings.agl.unicodes -- delayed end - return aglunicodes[code] + local u = aglunicodes[code] + if u then + -- unicodes[code] = u + return u + end end local coverup = otf.coverup diff --git a/tex/context/base/mkiv/font-oto.lua b/tex/context/base/mkiv/font-oto.lua index 4b986bd3b..c32a7af25 100644 --- a/tex/context/base/mkiv/font-oto.lua +++ b/tex/context/base/mkiv/font-oto.lua @@ -415,36 +415,42 @@ local function checkmathreplacements(tfmdata,fullname,fixitalics) for unicode, replacement in next, changed do local u = characters[unicode] local r = characters[replacement] - local n = u.next - local v = u.vert_variants - local h = u.horiz_variants - if fixitalics then - -- quite some warnings on stix ... - local ui = u.italic - if ui and not r.italic then + if u and r then + local n = u.next + local v = u.vert_variants + local h = u.horiz_variants + if fixitalics then + -- quite some warnings on stix ... + local ui = u.italic + if ui and not r.italic then + if trace_preparing then + report_prepare("using %i units of italic correction from %C for %U",ui,unicode,replacement) + end + r.italic = ui -- print(ui,ri) + end + end + if n and not r.next then if trace_preparing then - report_prepare("using %i units of italic correction from %C for %U",ui,unicode,replacement) + report_prepare("forcing %s for %C substituted by %U","incremental step",unicode,replacement) end - r.italic = ui -- print(ui,ri) + r.next = n end - end - if n and not r.next then - if trace_preparing then - report_prepare("forcing %s for %C substituted by %U","incremental step",unicode,replacement) + if v and not r.vert_variants then + if trace_preparing then + report_prepare("forcing %s for %C substituted by %U","vertical variants",unicode,replacement) + end + r.vert_variants = v end - r.next = n - end - if v and not r.vert_variants then - if trace_preparing then - report_prepare("forcing %s for %C substituted by %U","vertical variants",unicode,replacement) + if h and not r.horiz_variants then + if trace_preparing then + report_prepare("forcing %s for %C substituted by %U","horizontal variants",unicode,replacement) + end + r.horiz_variants = h end - r.vert_variants = v - end - if h and not r.horiz_variants then + else if trace_preparing then - report_prepare("forcing %s for %C substituted by %U","horizontal variants",unicode,replacement) + report_prepare("error replacing %C by %U",unicode,replacement) end - r.horiz_variants = h end end end diff --git a/tex/context/base/mkiv/font-set.mkvi b/tex/context/base/mkiv/font-set.mkvi index fe0fb6cad..aac83e1aa 100644 --- a/tex/context/base/mkiv/font-set.mkvi +++ b/tex/context/base/mkiv/font-set.mkvi @@ -46,7 +46,7 @@ % \def\font_preloads_reset_nullfont % this is needed because some macro packages (tikz) misuse \nullfont % {\dorecurse\plusseven{\fontdimen\recurselevel\nullfont\zeropoint}% keep en eye on this as: % \clf_resetnullfont % in luatex 0.70 this will also do the previous -% \globallet\font_preloads_reset_nullfont\relax} +% \glet\font_preloads_reset_nullfont\relax} \def\font_preload_check_mode {\doifelsemode{lmmath} diff --git a/tex/context/base/mkiv/grph-img.lua b/tex/context/base/mkiv/grph-img.lua new file mode 100644 index 000000000..3714b649e --- /dev/null +++ b/tex/context/base/mkiv/grph-img.lua @@ -0,0 +1,747 @@ +if not modules then modules = { } end modules ['grph-img'] = { + version = 1.001, + comment = "companion to grph-inc.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- The jpg identification and inclusion code is based on the code in \LUATEX\ but as we +-- use \LUA\ we can do it a bit cleaner. We can also use some helpers for reading from +-- file. We could make it even more lean and mean. When all works out ok I will clean +-- up this code a bit as we can divert more from luatex. + +local lower, strip = string.lower, string.strip +local round = math.round +local concat = table.concat +local suffixonly = file.suffix + +local files = utilities.files +local getsize = files.getsize +local readbyte = files.readbyte +local readstring = files.readstring +local readcardinal = files.readcardinal +local readcardinal2 = files.readcardinal2 +local readcardinal4 = files.readcardinal4 +local readcardinal2le = files.readcardinal2le +local readcardinal4le = files.readcardinal4le +local skipbytes = files.skip +local setposition = files.setposition +local getposition = files.getposition + +local setmetatableindex = table.setmetatableindex +local setmetatablecall = table.setmetatablecall + +local lpdf = lpdf or { } +local pdfmajorversion = lpdf.majorversion +local pdfminorversion = lpdf.minorversion + +local graphics = graphics or { } +local identifiers = { } +graphics.identifiers = identifiers + +do + + local colorspaces = { + [1] = 1, -- gray + [3] = 2, -- rgb + [4] = 3, -- cmyk + } + + local tags = { + [0xC0] = { name = "SOF0", }, -- baseline DCT + [0xC1] = { name = "SOF1", }, -- extended sequential DCT + [0xC2] = { name = "SOF2", }, -- progressive DCT + [0xC3] = { name = "SOF3", supported = false }, -- lossless (sequential) + + [0xC5] = { name = "SOF5", supported = false }, -- differential sequential DCT + [0xC6] = { name = "SOF6", supported = false }, -- differential progressive DCT + [0xC7] = { name = "SOF7", supported = false }, -- differential lossless (sequential) + + [0xC8] = { name = "JPG", }, -- reserved for JPEG extensions + [0xC9] = { name = "SOF9", }, -- extended sequential DCT + [0xCA] = { name = "SOF10", supported = false }, -- progressive DCT + [0xCB] = { name = "SOF11", supported = false }, -- lossless (sequential) + + [0xCD] = { name = "SOF13", supported = false }, -- differential sequential DCT + [0xCE] = { name = "SOF14", supported = false }, -- differential progressive DCT + [0xCF] = { name = "SOF15", supported = false }, -- differential lossless (sequential) + + [0xC4] = { name = "DHT" }, -- define Huffman table(s) + + [0xCC] = { name = "DAC" }, -- define arithmetic conditioning table + + [0xD0] = { name = "RST0", zerolength = true }, -- restart + [0xD1] = { name = "RST1", zerolength = true }, -- restart + [0xD2] = { name = "RST2", zerolength = true }, -- restart + [0xD3] = { name = "RST3", zerolength = true }, -- restart + [0xD4] = { name = "RST4", zerolength = true }, -- restart + [0xD5] = { name = "RST5", zerolength = true }, -- restart + [0xD6] = { name = "RST6", zerolength = true }, -- restart + [0xD7] = { name = "RST7", zerolength = true }, -- restart + + [0xD8] = { name = "SOI", zerolength = true }, -- start of image + [0xD9] = { name = "EOI", zerolength = true }, -- end of image + [0xDA] = { name = "SOS" }, -- start of scan + [0xDB] = { name = "DQT" }, -- define quantization tables + [0xDC] = { name = "DNL" }, -- define number of lines + [0xDD] = { name = "DRI" }, -- define restart interval + [0xDE] = { name = "DHP" }, -- define hierarchical progression + [0xDF] = { name = "EXP" }, -- expand reference image(s) + + [0xE0] = { name = "APP0" }, -- application marker, used for JFIF + [0xE1] = { name = "APP1" }, -- application marker + [0xE2] = { name = "APP2" }, -- application marker + [0xE3] = { name = "APP3" }, -- application marker + [0xE4] = { name = "APP4" }, -- application marker + [0xE5] = { name = "APP5" }, -- application marker + [0xE6] = { name = "APP6" }, -- application marker + [0xE7] = { name = "APP7" }, -- application marker + [0xE8] = { name = "APP8" }, -- application marker + [0xE9] = { name = "APP9" }, -- application marker + [0xEA] = { name = "APP10" }, -- application marker + [0xEB] = { name = "APP11" }, -- application marker + [0xEC] = { name = "APP12" }, -- application marker + [0xED] = { name = "APP13" }, -- application marker + [0xEE] = { name = "APP14" }, -- application marker, used by Adobe + [0xEF] = { name = "APP15" }, -- application marker + + [0xF0] = { name = "JPG0" }, -- reserved for JPEG extensions + [0xFD] = { name = "JPG13" }, -- reserved for JPEG extensions + [0xFE] = { name = "COM" }, -- comment + + [0x01] = { name = "TEM", zerolength = true }, -- temporary use + } + + -- More can be found in http://www.exif.org/Exif2-2.PDF but basically we have + -- good old tiff tags here. + + local function read_APP1_Exif(f, xres, yres, orientation) -- untested + local position = false + local readcardinal2 = readcardinal2 + local readcardinal4 = readcardinal4 + -- endian II|MM + while true do + position = getposition(f) + local b = readbyte(f) + if b == 0 then + -- next one + elseif b == 0x4D and readbyte(f) == 0x4D then -- M + -- big endian + break + elseif b == 0x49 and readbyte(f) == 0x49 then -- I + -- little endian + readcardinal2 = readcardinal2le + readcardinal4 = readcardinal4le + break + else + -- warning "bad exif data" + return xres, yres, orientation + end + end + -- version + local version = readcardinal2(f) + if version ~= 42 then + return xres, yres, orientation + end + -- offset to records + local offset = readcardinal4(f) + if not offset then + return xres, yres, orientation + end + setposition(f,position + offset) + local entries = readcardinal2(f) + if not entries or entries == 0 then + return xres, yres, orientation + end + local x_res, y_res, x_res_ms, y_res_ms, x_temp, y_temp + local res_unit, res_unit_ms + for i=1,entries do + local tag = readcardinal2(f) + local kind = readcardinal2(f) + local size = readcardinal4(f) + local value = 0 + local num = 0 + local den = 0 + if kind == 1 or kind == 7 then -- byte | undefined + value = readbyte(f) + skipbytes(f,3) + elseif kind == 3 or kind == 8 then -- (un)signed short + value = readcardinal2(f) + skipbytes(f,2) + elseif kind == 4 or kind == 9 then -- (un)signed long + value = readcardinal4(f) + elseif kind == 5 or kind == 10 then -- (s)rational + local offset = readcardinal4(f) + local saved = getposition(f) + setposition(f,position+offset) + num = readcardinal4(f) + den = readcardinal4(f) + setposition(f,saved) + else -- 2 -- ascii + skipbytes(f,4) + end + if tag == 274 then -- orientation + orientation = value + elseif tag == 282 then -- x resolution + if den ~= 0 then + x_res = num/den + end + elseif tag == 283 then -- y resolution + if den ~= 0 then + y_res = num/den + end + elseif tag == 296 then -- resolution unit + if value == 2 then + res_unit = 1 + elseif value == 3 then + res_unit = 2.54 + end + elseif tag == 0x5110 then -- pixel unit + res_unit_ms = value == 1 + elseif tag == 0x5111 then -- x pixels per unit + x_res_ms = value + elseif tag == 0x5112 then -- y pixels per unit + y_res_ms = value + end + end + if x_res and y_res and res_unit and res_unit > 0 then + x_temp = round(x_res * res_unit) + y_temp = round(y_res * res_unit) + elseif x_res_ms and y_res_ms and res_unit_ms then + x_temp = round(x_res_ms * 0.0254) -- in meters + y_temp = round(y_res_ms * 0.0254) -- in meters + end + if x_temp and a_temp and x_temp > 0 and y_temp > 0 then + if (x_temp ~= x_res or y_temp ~= y_res) and x_res ~= 0 and y_res ~= 0 then + -- exif resolution differs from already found resolution + elseif x_temp == 1 or y_temp == 1 then + -- exif resolution is kind of weird + else + return x_temp, y_temp, orientation + end + end + return round(xres), round(yres), orientation + end + + function identifiers.jpg(filename) + local specification = { + filename = filename, + filetype = "jpg", + } + if not filename or filename == "" then + specification.error = "invalid filename" + return specification -- error + end + local f = io.open(filename,"rb") + if not f then + specification.error = "unable to open file" + return specification -- error + end + specification.xres = 0 + specification.yres = 0 + specification.orientation = 1 + specification.totalpages = 1 + specification.pagenum = 1 + specification.length = 0 + local banner = readcardinal2(f) + if banner ~= 0xFFD8 then + specification.error = "no jpeg file" + return specification -- error + end + local xres = 0 + local yres = 0 + local orientation = 1 + local okay = false + local filesize = getsize(f) -- seek end + local majorversion = pdfmajorversion and pdfmajorversion() or 2 + local minorversion = pdfminorversion and pdfminorversion() or 2 + while getposition(f) < filesize do + local b = readbyte(f) + if not b then + break + elseif b ~= 0xFF then + if not okay then + -- or check for size + specification.error = "incomplete file" + end + break + end + local category = readbyte(f) + local position = getposition(f) + local length = 0 + local tagdata = tags[category] + if not tagdata then + specification.error = "invalid tag" + break + elseif tagdata.supported == false then + specification.error = "unsupported " .. tagdata.comment + break + end + local name = tagdata.name + if name == "SOF2" then + if majorversion < 2 or minorversion <= 2 then + specification.error = "no progressive DCT in PDF <= 1.2" + break + end + elseif name == "SOF0" or name == "SOF1" then + length = readcardinal2(f) + specification.colordepth = readcardinal(f) + specification.ysize = readcardinal2(f) + specification.xsize = readcardinal2(f) + specification.colorspace = colorspaces[readcardinal(f)] + if not specification.colorspace then + specification.error = "unsupported color space" + break + end + okay = true + elseif name == "APP0" then + length = readcardinal2(f) + if length > 6 then + local format = readstring(f,5) + if format == "JFIF\000" then + skipbytes(f,2) + units = readcardinal(f) + xres = readcardinal2(f) + yres = readcardinal2(f) + if units == 1 then + -- pixels per inch + if xres == 1 or yres == 1 then + -- warning + end + elseif units == 2 then + -- pixels per cm */ + xres = xres * 2.54 + yres = yres * 2.54 + else + xres = 0 + yres = 0 + end + end + end + elseif name == "APP1" then + length = readcardinal2(f) + if length > 7 then + local format = readstring(f,5) + if format == "Exif\000" then + xres, yres, orientation = read_APP1_Exif(f,xres,yres,orientation) + end + end + elseif not tagdata.zerolength then + length = readcardinal2(f) + end + if length > 0 then + setposition(f,position+length) + end + end + f:close() + if not okay then + specification.error = "invalid file" + elseif not specification.error then + if xres == 0 and yres ~= 0 then + xres = yres + end + if yres == 0 and xres ~= 0 then + yres = xres + end + end + specification.xres = xres + specification.yres = yres + specification.orientation = orientation + specification.length = filesize + return specification + end + +end + +do + + local function read_boxhdr(specification,f) + local size = readcardinal4(f) + local kind = readstring(f,4) + if kind then + kind = strip(lower(kind)) + else + kind = "" + end + if size == 1 then + size = readcardinal4(f) * 0xFFFF0000 + readcardinal4(f) + end + if size == 0 and kind ~= "jp2c" then -- move this + specification.error = "invalid size" + end + return kind, size + end + + local function scan_ihdr(specification,f) + specification.ysize = readcardinal4(f) + specification.xsize = readcardinal4(f) + skipbytes(f,2) -- nc + specification.colordepth = readcardinal(f) + 1 + skipbytes(f,3) -- c unkc ipr + end + + local function scan_resc_resd(specification,f) + local vr_n = readcardinal2(f) + local vr_d = readcardinal2(f) + local hr_n = readcardinal2(f) + local hr_d = readcardinal2(f) + local vr_e = readcardinal(f) + local hr_e = readcardinal(f) + specification.xres = math.round((hr_n / hr_d) * math.exp(hr_e * math.log(10.0)) * 0.0254) + specification.yres = math.round((vr_n / vr_d) * math.exp(vr_e * math.log(10.0)) * 0.0254) + end + + local function scan_res(specification,f,last) + local pos = getposition(f) + while true do + local kind, size = read_boxhdr(specification,f) + pos = pos + size + if kind == "resc" then + if specification.xres == 0 and specification.yres == 0 then + scan_resc_resd(specification,f) + if getposition(f) ~= pos then + specification.error = "invalid resc" + return + end + end + elseif tpos == "resd" then + scan_resc_resd(specification,f) + if getposition(f) ~= pos then + specification.error = "invalid resd" + return + end + elseif pos > last then + specification.error = "invalid res" + return + elseif pos == last then + break + end + if specification.error then + break + end + setposition(f,pos) + end + end + + local function scan_jp2h(specification,f,last) + local okay = false + local pos = getposition(f) + while true do + local kind, size = read_boxhdr(specification,f) + pos = pos + size + if kind == "ihdr" then + scan_ihdr(specification,f) + if getposition(f) ~= pos then + specification.error = "invalid ihdr" + return false + end + okay = true + elseif kind == "res" then + scan_res(specification,f,pos) + elseif pos > last then + specification.error = "invalid jp2h" + return false + elseif pos == last then + break + end + if specification.error then + break + end + setposition(f,pos) + end + return okay + end + + function identifiers.jp2(filename) + local specification = { + filename = filename, + filetype = "jp2", + } + if not filename or filename == "" then + specification.error = "invalid filename" + return specification -- error + end + local f = io.open(filename,"rb") + if not f then + specification.error = "unable to open file" + return specification -- error + end + specification.xres = 0 + specification.yres = 0 + specification.orientation = 1 + specification.totalpages = 1 + specification.pagenum = 1 + specification.length = 0 + local xres = 0 + local yres = 0 + local orientation = 1 + local okay = false + local filesize = getsize(f) -- seek end + local majorversion = pdfmajorversion and pdfmajorversion() or 2 + local minorversion = pdfminorversion and pdfminorversion() or 2 + -- + local pos = 0 + -- signature + local kind, size = read_boxhdr(specification,f) + pos = pos + size + setposition(f,pos) + -- filetype + local kind, size = read_boxhdr(specification,f) + if kind ~= "ftyp" then + specification.error = "missing ftyp box" + return specification + end + pos = pos + size + setposition(f,pos) + while not okay do + local kind, size = read_boxhdr(specification,f) + pos = pos + size + if kind == "jp2h" then + okay = scan_jp2h(specification,f,pos) + elseif kind == "jp2c" and not okay then + specification.error = "no ihdr box found" + return specification + end + setposition(f,pos) + end + -- + f:close() + if not okay then + specification.error = "invalid file" + elseif not specification.error then + if xres == 0 and yres ~= 0 then + xres = yres + end + if yres == 0 and xres ~= 0 then + yres = xres + end + end + specification.xres = xres + specification.yres = yres + specification.orientation = orientation + specification.length = filesize + return specification + end + +end + +do + + -- 0 = gray "image b" + -- 2 = rgb "image c" + -- 3 = palette "image c" + "image i" + -- 4 = gray + alpha "image b" + -- 6 = rgb + alpha "image c" + + -- for i=1,length/3 do + -- palette[i] = readstring(f,3) + -- end + + local function grab(t,f,once) + if once then + for i=1,#t do + local l = t[i] + setposition(f,l.offset) + t[i] = readstring(f,l.length) + end + local data = concat(t) + return data + else + local data = { } + for i=1,#t do + local l = t[i] + setposition(f,l.offset) + data[i] = readstring(f,l.length) + end + return concat(data) + end + end + + function identifiers.png(filename) + local specification = { + filename = filename, + filetype = "png", + } + if not filename or filename == "" then + specification.error = "invalid filename" + return specification -- error + end + local f = io.open(filename,"rb") + if not f then + specification.error = "unable to open file" + return specification -- error + end + specification.xres = 0 + specification.yres = 0 + specification.orientation = 1 + specification.totalpages = 1 + specification.pagenum = 1 + specification.offset = 0 + specification.length = 0 + local filesize = getsize(f) -- seek end + local tables = { } + local banner = readstring(f,8) + if banner ~= "\137PNG\013\010\026\010" then + specification.error = "no png file" + return specification -- error + end + while true do + local position = getposition(f) + if position >= filesize then + break + end + local length = readcardinal4(f) + if not length then + break + end + local kind = readstring(f,4) + if kind then + kind = lower(kind) + else + break + end + if kind == "ihdr" then -- metadata + specification.xsize = readcardinal4(f) + specification.ysize = readcardinal4(f) + specification.colordepth = readcardinal(f) + specification.colorspace = readcardinal(f) + specification.compression = readcardinal(f) + specification.filter = readcardinal(f) + specification.interlace = readcardinal(f) + tables[kind] = true + elseif kind == "iend" then + tables[kind] = true + break + elseif kind == "phys" then + local x = readcardinal4(f) + local y = readcardinal4(f) + local u = readcardinal(f) + if u == 1 then -- meters + -- x = round(0.0254 * x) + -- y = round(0.0254 * y) + end + specification.xres = x + specification.yres = y + tables[kind] = true + elseif kind == "idat" or kind == "plte" or kind == "gama" or kind == "trns" then + local t = tables[kind] + if not t then + t = setmetatablecall(grab) + tables[kind] = t + end + t[#t+1] = { + offset = getposition(f), + length = length, + } + else + tables[kind] = true + end + setposition(f,position+length+12) -- #size #kind #crc + end + specification.tables = tables + return specification + end + +end + +do + + local function gray(t,k) + local v = 0 + t[k] = v + return v + end + + local function rgb(t,k) + local v = { 0, 0, 0 } + t[k] = v + return v + end + + local function cmyk(t,k) + local v = { 0, 0, 0, 0 } + t[k] = v + return v + end + + function identifiers.bitmap(specification) + local xsize = specification.xsize or 0 + local ysize = specification.ysize or 0 + local width = specification.width or xsize * 65536 + local height = specification.height or ysize * 65536 + local colordepth = specification.colordepth or 1 -- 1 .. 2 + local colorspace = specification.colorspace or 1 -- 1 .. 3 + local pixel = false + local data = specification.data + local mask = specification.mask + if colorspace == 1 or colorspace == "gray" then + pixel = gray + colorspace = 1 + elseif colorspace == 2 or colorspace == "rgb" then + pixel = rgb + colorspace = 2 + elseif colorspace == 3 or colorspace == "cmyk" then + pixel = cmyk + colorspace = 3 + else + return + end + -- maybe alpha some day + if colordepth == 8 then + colordepth = 1 + elseif colordepth == 16 then + colordepth = 2 + end + if colordepth > 1 then + -- not yet + return + end + if data then + -- assume correct data + else + data = { } + for i=1,ysize do + data[i] = setmetatableindex(pixel) + end + end + if mask == true then + mask = { } + for i=1,ysize do + mask[i] = setmetatableindex(gray) + end + end + local specification = { + xsize = xsize, + ysize = ysize, + width = width, + height = height, + colordepth = colordepth, + colorspace = colorspace, + data = data, + mask = mask, + } + return specification + end + +end + +function graphics.identify(filename,filetype) + local identify = filetype and identifiers[filetype] + if identify then + return identify(filename) + end + local identify = identifiers[suffixonly(filename)] + if identify then + return identify(filename) + end + -- auto + return { + filename = filename, + filetype = filetype, + error = "identification failed", + } +end + +-- inspect(identifiers.jpg("t:/sources/hacker.jpg")) +-- inspect(identifiers.png("t:/sources/mill.png")) diff --git a/tex/context/base/mkiv/grph-inc.lua b/tex/context/base/mkiv/grph-inc.lua index 09084606d..553c60463 100644 --- a/tex/context/base/mkiv/grph-inc.lua +++ b/tex/context/base/mkiv/grph-inc.lua @@ -60,6 +60,8 @@ local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex local replacetemplate = utilities.templates.replace +-- local bpfactor = number.dimenfactors.bp + local images = img local hasscheme = url.hasscheme @@ -2139,6 +2141,126 @@ local function pdf_checker(data) return checkers.generic(data) end +local function wrappedidentify(identify,filename) + local wrapup = function() report_inclusion("fatal error reading %a",filename) end + local _, result = xpcall(identify,wrapup,filename) + return result or { error = "fatal error" } +end + +local function jpg_checker(data) + local request = data.request + local used = data.used + if request and used and not request.scanimage then + local identify = graphics.identify + local inject = lpdf.injectors.jpg + local found = false + request.scanimage = function(t) + local filename = t.filename + local result = wrappedidentify(identify,filename) + local xsize = result.xsize or 0 + local ysize = result.ysize or 0 + found = not result.error + return { + filename = filename, + width = xsize * 65536, + height = ysize * 65536, + depth = 0, + colordepth = result.colordepth or 0, + xres = result.xres, + yres = result.yres, + xsize = xsize, + ysize = ysize, + rotation = result.rotation or 0, + colorspace = result.colorspace or 0, + } + end + request.copyimage = function(t) + if found then + found = false + return inject(t) + end + end + end + return checkers.generic(data) +end + +local function jp2_checker(data) -- idem as jpg + local request = data.request + local used = data.used + if request and used and not request.scanimage then + local identify = graphics.identify + local inject = lpdf.injectors.jp2 + local found = false + request.scanimage = function(t) + local filename = t.filename + local result = wrappedidentify(identify,filename) + local xsize = result.xsize or 0 + local ysize = result.ysize or 0 + found = not result.error + return { + filename = filename, + width = xsize * 65536, + height = ysize * 65536, + depth = 0, + colordepth = result.colordepth or 0, + xres = result.xres, + yres = result.yres, + xsize = xsize, + ysize = ysize, + rotation = result.rotation or 0, + colorspace = result.colorspace or 0, + } + end + request.copyimage = function(t) + if found then + found = false + return inject(t) + end + end + end + return checkers.generic(data) +end + +local function png_checker(data) -- same as jpg (for now) + local request = data.request + local used = data.used + if request and used and not request.scanimage then + local identify = graphics.identify + local inject = lpdf.injectors.png + local found = false + request.scanimage = function(t) + local filename = t.filename + local result = wrappedidentify(identify,filename) + local xsize = result.xsize or 0 + local ysize = result.ysize or 0 + found = not result.error + return { + filename = filename, + width = xsize * 65536, + height = ysize * 65536, + depth = 0, + colordepth = result.colordepth or 0, + xres = result.xres, + yres = result.yres, + xsize = xsize, + ysize = ysize, + rotation = result.rotation or 0, + colorspace = result.colorspace or 0, + tables = result.tables, + interlace = result.interlace, + filter = result.filter, + } + end + request.copyimage = function(t) + if found then + found = false + return inject(t) + end + end + end + return checkers.generic(data) +end + directives.register("graphics.pdf.uselua",function(v) if v then report("%s Lua based PDF inclusion","enabling") @@ -2149,6 +2271,37 @@ directives.register("graphics.pdf.uselua",function(v) end end) +directives.register("graphics.jpg.uselua",function(v) + if v then + report("%s Lua based JPG inclusion","enabling") + checkers.jpg = jpg_checker + else + report("%s Lua based JPG inclusion","disabling") + checkers.jpg = nil + end +end) + +directives.register("graphics.jp2.uselua",function(v) + if v then + report("%s Lua based JP2 inclusion","enabling") + checkers.jp2 = jp2_checker + else + report("%s Lua based JP2 inclusion","disabling") + checkers.jp2 = nil + end +end) + +directives.register("graphics.png.uselua",function(v) + if v then + report("%s Lua based PNG inclusion","enabling") + checkers.png = png_checker + else + report("%s Lua based PNG inclusion","disabling") + checkers.png = nil + end +end) + + -- directives.enable("graphics.pdf.uselua") -- -- local filename = "luatex.pdf" @@ -2160,3 +2313,62 @@ end) -- context.stopTEXpage() -- end) -- end + +-- This is experimental, for the moment here: + +local bitmaps = { } +graphics.bitmaps = bitmaps + +local report_bitmap = logs.reporter("graphics","bitmap") + +function bitmaps.new(xsize,ysize,colorspace,colordepth,mask) + if not xsize or not ysize or xsize == 0 or ysize == 0 then + report_bitmap("provide 'xsize' and 'ysize' larger than zero") + return + end + if not colorspace then + report_bitmap("provide 'colorspace' (1, 2, 3, 'gray', 'rgb', 'cmyk'") + return + end + if not colordepth then + report_bitmap("provide 'colordepth' (1, 2)") + return + end + return graphics.identifiers.bitmap { + colorspace = colorspace, + colordepth = colordepth, + xsize = xsize, + ysize = ysize, + mask = mask and true or nil, + } +end + +local function flush(bitmap) + img.write(lpdf.injectors.bitmap(bitmap)) +end + +bitmaps.flush = flush + +function bitmaps.tocontext(bitmap,width,height) + if type(width) == "number" then + width = width .. "sp" + end + if type(height) == "number" then + height = height .. "sp" + end + if not height and not height then + width = bitmap.xsize .. "bp" + height = bitmap.ysize .. "bp" + end + context.scale ( + { + width = width, + height = height, + }, + function() + flush(bitmap) + end + ) +end + + diff --git a/tex/context/base/mkiv/grph-inc.mkiv b/tex/context/base/mkiv/grph-inc.mkiv index 371725271..cefb114e9 100644 --- a/tex/context/base/mkiv/grph-inc.mkiv +++ b/tex/context/base/mkiv/grph-inc.mkiv @@ -20,6 +20,7 @@ \writestatus{loading}{ConTeXt Graphic Macros / Figure Inclusion} +\registerctxluafile{grph-img}{} \registerctxluafile{grph-inc}{} \registerctxluafile{grph-con}{} \registerctxluafile{grph-fil}{} diff --git a/tex/context/base/mkiv/l-macro-imp-optimize.lua b/tex/context/base/mkiv/l-macro-imp-optimize.lua index 856cab038..982548785 100644 --- a/tex/context/base/mkiv/l-macro-imp-optimize.lua +++ b/tex/context/base/mkiv/l-macro-imp-optimize.lua @@ -57,6 +57,7 @@ lua.macros.resolvestring [[ #define extract(a,b) ((a>>b)&0x1) #define lshift(a,b) ((a<<b)&0xFFFFFFFF) #define rshift(a,b) ((a>>b)&0xFFFFFFFF) +#define intdiv(a,b) (a//b) ]] end diff --git a/tex/context/base/mkiv/l-number.lua b/tex/context/base/mkiv/l-number.lua index a83e8f8f9..dc4a93b0e 100644 --- a/tex/context/base/mkiv/l-number.lua +++ b/tex/context/base/mkiv/l-number.lua @@ -232,3 +232,7 @@ function number.decimaltobyte(d) return b end end + +function number.idiv(i,d) + return floor(i/d) -- i//d in 5.3 +end diff --git a/tex/context/base/mkiv/lpdf-img.lua b/tex/context/base/mkiv/lpdf-img.lua new file mode 100644 index 000000000..28890887a --- /dev/null +++ b/tex/context/base/mkiv/lpdf-img.lua @@ -0,0 +1,1061 @@ +if not modules then modules = { } end modules ['lpdf-img'] = { + version = 1.001, + comment = "companion to lpdf-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local concat, remove, insert = table.concat, table.remove, table.insert +local ceil = math.ceil +local char, find = string.char, string.find +local idiv = number.idiv +local band, rshift = bit32.band, bit32.rshift + +local loaddata = io.loaddata +local setmetatableindex = table.setmetatableindex + +local streams = utilities.streams +local openstring = streams.openstring +local readstring = streams.readstring +local readbytetable = streams.readbytetable + +local lpdf = lpdf or { } +local pdfdictionary = lpdf.dictionary +local pdfarray = lpdf.array +local pdfconstant = lpdf.constant +local pdfstring = lpdf.string +local pdfflushstreamobject = lpdf.flushstreamobject +local pdfreference = lpdf.reference + +local pdfmajorversion = lpdf.majorversion +local pdfminorversion = lpdf.minorversion + +local newimage = img.new + +local trace = false + +local report_jpg = logs.reporter("graphics","jpg") +local report_jp2 = logs.reporter("graphics","jp2") +local report_png = logs.reporter("graphics","png") + +local injectors = { } +lpdf.injectors = injectors + +local chars = setmetatableindex(function(t,k) -- share this one + local v = (k <= 0 and "\000") or (k >= 255 and "\255") or char(k) + t[k] = v + return v +end) + +do + + function injectors.jpg(specification) + if specification.error then + return + end + local filename = specification.filename + if not filename then + return + end + local colorspace = specification.colorspace or jpg_gray + local attributes = specification.attr + local decodearray = nil + ----- procset = colorspace == 0 and "image b" or "image c" + if colorspace == 1 then + colorspace = "DeviceGray" + elseif colorspace == 2 then + colorspace = "DeviceRGB" + elseif colorspace == 3 then + colorspace = "DeviceCMYK" + decodearray = pdfarray { 1, 0, 1, 0, 1, 0, 1, 0 } + end + -- todo: set filename + local xsize = specification.xsize + local ysize = specification.ysize + local colordepth = specification.colordepth + local content = loaddata(filename) + local xobject = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Image"), + BBox = pdfarray { 0, 0, xsize, ysize }, + Width = xsize, + Height = ysize, + BitsPerComponent = colordepth, + Filter = pdfconstant("DCTDecode"), + ColorSpace = pdfconstant(colorspace), + Decode = decodearray, + Length = #content, -- specification.length + } + if attributes then + -- todo: add attributes to d + end + if trace then + report_jpg("%s: width %i, height %i, colordepth %i, size %i",filename,xsize,ysize,colordepth,#content) + end + return newimage { + bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate + nolength = true, + nobbox = true, + notype = true, + stream = content, + attr = xobject(), + } + end + +end + +do + + function injectors.jp2(specification) + if specification.error then + return + end + local filename = specification.filename + if not filename then + return + end + local attributes = specification.attr + -- todo: set filename + local xsize = specification.xsize + local ysize = specification.ysize + local content = loaddata(filename) + local xobject = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Image"), + BBox = pdfarray { 0, 0, xsize, ysize }, + Width = xsize, + Height = ysize, + Filter = pdfconstant("JPXDecode"), + Length = #content, -- specification.length + } + if attributes then + -- todo: add attributes to d + end + if trace then + report_jp2("%s: width %i, height %i, size %i",filename,xsize,ysize,#content) + end + return newimage { + bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate + nolength = true, + nobbox = true, + notype = true, + stream = content, + attr = xobject(), + } + end + +end + +do + + -- We don't like interlaced files. You can deinterlace them beforehand because otherwise + -- each run you add runtime. Actually, even masked images can best be converted to PDF + -- beforehand. + + -- The amount of code is larger that I like and looks somewhat redundant but we sort of + -- optimize a few combinations that happen often. + + local function convert(t,len) + if len then +local n = 0 + for i=1,#t,len do + t[i] = "" +n = n + 1 + end + end + for i=1,#t do + local ti = t[i] + if ti ~= "" then + t[i] = chars[ti] + end + end + return concat(t) + end + + local function zero(t,k) + return 0 + end + + local function bump(txt,t,xsize,ysize,bpp) + local l = xsize * bpp + 1 + print(txt,">",xsize,ysize,bpp,l) + for i=1,ysize do + local f = (i-1) * l + 1 + print(txt,i,":",concat(t," ",f,f+l-1)) + end + end + + local function decodeall(t,xsize,ysize,bpp) + local len = xsize * bpp + 1 + local n = 1 + local m = len - 1 + for i=1,ysize do + local filter = t[n] +t[n] = 0 -- not needed + if filter == 0 then + elseif filter == 1 then + for j=n+bpp+1,n+m do + t[j] = (t[j] + t[j-bpp]) % 256 + end + elseif filter == 2 then + for j=n+1,n+m do + t[j] = (t[j] + t[j-len]) % 256 + end + elseif filter == 3 then + for j=n+1,n+bpp do + t[j] = (t[j] + idiv(t[j-len],2)) % 256 + end + for j=n+bpp+1,n+m do + t[j] = (t[j] + idiv(t[j-bpp] + t[j-len],2)) % 256 + end + elseif filter == 4 then + for j=n+1,n+bpp do + local p = j - len + local b = t[p] + if b < 0 then + b = - b + end + if b > 0 then + t[j] = (t[j] + b) % 256 + end + end + for j=n+bpp+1,n+m do + local p = j - len + local a = t[j-bpp] + local b = t[p] + local c = t[p-bpp] + local pa = b - c + local pb = a - c + local pc = pa + pb + if pa < 0 then pa = - pa end + if pb < 0 then pb = - pb end + if pc < 0 then pc = - pc end + t[j] = (t[j] + ((pa <= pb and pa <= pc and a) or (pb <= pc and b) or c)) % 256 + end + end + n = n + len + end + end + + local xstart = { 0, 4, 0, 2, 0, 1, 0 } + local xstep = { 8, 8, 4, 4, 2, 2, 1 } + local ystart = { 0, 0, 4, 0, 2, 0, 1 } + local ystep = { 8, 8, 8, 4, 4, 2, 2 } + ----- xmax = { 8, 4, 4, 2, 2, 1, 1 } -- for block fill + ----- ymax = { 8, 8, 4, 4, 2, 2, 1 } -- for block fill + + local function newoutput(width,height) + local t = { } + for i=1,height*width do + t[i] = 0 + end + return t + end + + local function expand(t,xsize,ysize,parts,factor) -- we don't compact + local o = { } + local k = 0 + local l = ceil(xsize*parts/8) + 1 + local n = 1 + if factor then + if parts == 4 then + for i=1,ysize do + k = k + 1 ; o[k] = t[n] + for j=n+1,n+l do + local v = t[j] + k = k + 1 ; o[k] = band(rshift(v,4),0x0F) * 0x11 ; k = k + 1 ; o[k] = band(rshift(v,0),0x0F) * 0x11 + end + k = i * (xsize + 1) + n = n + l + end + elseif parts == 2 then + for i=1,ysize do + k = k + 1 ; o[k] = t[n] + for j=n+1,n+l do + local v = t[j] + k = k + 1 ; o[k] = band(rshift(v,6),0x03) * 0x55 ; k = k + 1 ; o[k] = band(rshift(v,4),0x03) * 0x55 + k = k + 1 ; o[k] = band(rshift(v,2),0x03) * 0x55 ; k = k + 1 ; o[k] = band(rshift(v,0),0x03) * 0x55 + end + k = i * (xsize + 1) + n = n + l + end + else + for i=1,ysize do + k = k + 1 ; o[k] = t[n] + for j=n+1,n+l do + local v = t[j] + k = k + 1 ; o[k] = band(rshift(v,7),0x01) * 0xFF ; k = k + 1 ; o[k] = band(rshift(v,6),0x01) * 0xFF + k = k + 1 ; o[k] = band(rshift(v,5),0x01) * 0xFF ; k = k + 1 ; o[k] = band(rshift(v,4),0x01) * 0xFF + k = k + 1 ; o[k] = band(rshift(v,3),0x01) * 0xFF ; k = k + 1 ; o[k] = band(rshift(v,2),0x01) * 0xFF + k = k + 1 ; o[k] = band(rshift(v,1),0x01) * 0xFF ; k = k + 1 ; o[k] = band(rshift(v,0),0x01) * 0xFF + end + k = i * (xsize + 1) + n = n + l + end + end + else + if parts == 4 then + for i=1,ysize do + k = k + 1 ; o[k] = t[n] + for j=n+1,n+l do + local v = t[j] + k = k + 1 ; o[k] = band(rshift(v,4),0x0F) ; k = k + 1 ; o[k] = band(rshift(v,0),0x0F) + end + k = i * (xsize + 1) + n = n + l + end + elseif parts == 2 then + for i=1,ysize do + k = k + 1 ; o[k] = t[n] + for j=n+1,n+l do + local v = t[j] + k = k + 1 ; o[k] = band(rshift(v,6),0x03) ; k = k + 1 ; o[k] = band(rshift(v,4),0x03) + k = k + 1 ; o[k] = band(rshift(v,2),0x03) ; k = k + 1 ; o[k] = band(rshift(v,0),0x03) + end + k = i * (xsize + 1) + n = n + l + end + else + for i=1,ysize do + k = k + 1 ; o[k] = t[n] + for j=n+1,n+l do + local v = t[j] + k = k + 1 ; o[k] = band(rshift(v,7),0x01) ; k = k + 1 ; o[k] = band(rshift(v,6),0x01) + k = k + 1 ; o[k] = band(rshift(v,5),0x01) ; k = k + 1 ; o[k] = band(rshift(v,4),0x01) + k = k + 1 ; o[k] = band(rshift(v,3),0x01) ; k = k + 1 ; o[k] = band(rshift(v,2),0x01) + k = k + 1 ; o[k] = band(rshift(v,1),0x01) ; k = k + 1 ; o[k] = band(rshift(v,0),0x01) + end + k = i * (xsize + 1) + n = n + l + end + end + end + for i=#o,k+1,-1 do + o[i] = nil + end + return o + end + + local function deinterlaceXX(s,xsize,ysize,bytes,parts,factor) + local output = newoutput(xsize*bytes,ysize) + for pass=1,7 do + local ystart = ystart[pass] + local ystep = ystep[pass] + local xstart = xstart[pass] + local xstep = xstep[pass] + local nx = idiv(xsize + xstep - xstart - 1,xstep) + local ny = idiv(ysize + ystep - ystart - 1,ystep) + if nx > 0 and ny > 0 then + local input + if parts then + local nxx = ceil(nx*parts/8) + input = readbytetable(s,ny*(nxx+1)) + setmetatableindex(input,zero) + decodeall(input,nxx,ny,bytes) + input = expand(input,nx,ny,parts,factor) + else + input = readbytetable(s,ny*(nx*bytes+1)) + setmetatableindex(input,zero) + decodeall(input,nx,ny,bytes) + end + local l = nx*bytes + 1 + for i=ny,1,-1 do + remove(input,(i-1)*l+1) + end + local xstep = xstep * bytes + local xstart = xstart * bytes + local xsize = xsize * bytes + local target = ystart * xsize + xstart + 1 + local ystep = ystep * xsize + local start = 1 + local blobs = bytes - 1 + for j=0,ny-1 do + local target = target + j * ystep + for i=1,nx do + for i=0,blobs do + output[target+i] = input[start] + start= start + 1 + end + target = target + xstep + end + end + end + end + return output + end + + local function deinterlaceYY(s,xsize,ysize,bytes,parts,factor) + local input + if parts then + local nxx = ceil(xsize*parts/8) + input = readbytetable(s,ysize*(nxx+1)) + setmetatableindex(input,zero) + decodeall(input,nxx,ysize,bytes) + input = expand(input,xsize,ysize,parts,factor) + else + input = readbytetable(s,ysize*(xsize*bytes+1)) + setmetatableindex(input,zero) + decodeall(input,xsize,ysize,bytes) + end + local l = xsize*bytes + 1 + local n = 1 + for i=1,ysize do + input[n] = "" + n = n + l + end + return input + end + + local function analyze(colordepth,colorspace,palette,mask) + local bytes, parts, factor + if palette then + if colordepth == 16 then + return 2, false, false + elseif colordepth == 8 then + return 1, false, false + elseif colordepth == 4 then + return 1, 4, false + elseif colordepth == 2 then + return 1, 2, false + elseif colordepth == 1 then + return 1, 1, false + end + elseif colorspace == "DeviceGray" then + if colordepth == 16 then + return mask and 4 or 2, false, false + elseif colordepth == 8 then + return mask and 2 or 1, false, false + elseif colordepth == 4 then + return 1, 4, true + elseif colordepth == 2 then + return 1, 2, true + elseif colordepth == 1 then + return 1, 1, true + end + else + if colordepth == 16 then + return mask and 8 or 6, false, false + elseif colordepth == 8 then + return mask and 4 or 3, false, false + elseif colordepth == 4 then + return 3, 4, true + elseif colordepth == 2 then + return 3, 2, true + elseif colordepth == 1 then + return 3, 1, true + end + end + return false, false, false + end + + local function deinterlace(content,xsize,ysize,colordepth,colorspace,palette,mask) + local bytes, parts, factor = analyze(colordepth,colorspace,palette,mask) + if bytes then + content = zlib.decompress(content) + local s = openstring(content) + local r = deinterlaceXX(s,xsize,ysize,bytes,parts,factor) + return r, parts and 8 or false + end + end + + local function decompose(content,xsize,ysize,colordepth,colorspace,palette,mask) + local bytes, parts, factor = analyze(colordepth,colorspace,palette,mask) + if bytes then + content = zlib.decompress(content) + local s = openstring(content) + local r = deinterlaceYY(s,xsize,ysize,bytes,parts,factor) + return r, parts and 8 or false + end + end + + -- 1 (palette used), 2 (color used), and 4 (alpha channel used) + + -- paeth: + -- + -- p = a + b - c + -- pa = abs(p - a) => a + b - c - a => b - c + -- pb = abs(p - b) => a + b - c - b => a - c + -- pc = abs(p - c) => a + b - c - c => a + b - c - c => a - c + b - c => pa + pb + + local function prepareimage(content,xsize,ysize,depth,colorspace,mask) + local bpp = (depth == 16 and 2 or 1) * ((colorspace == "DeviceRGB" and 3 or 1) + mask) local len = bpp * xsize + 1 + local s = openstring(content) + local t = readbytetable(s,#content) + setmetatableindex(t,zero) + return t, bpp, len + end + + local function filtermask08(xsize,ysize,t,bpp,len,n) + local mask = { } + local l = 0 + local m = len - n + for i=1,ysize do + for j=n+bpp,n+m,bpp do + l = l + 1 ; mask[l] = chars[t[j]] ; t[j] = "" + end + n = n + len + end + return concat(mask) + end + + local function filtermask16(xsize,ysize,t,bpp,len,n) + local mask = { } + local l = 0 + local m = len - n + for i=1,ysize do + for j=n+bpp-1,n+m-1,bpp do + l = l + 1 ; mask[l] = chars[t[j]] ; t[j] = "" + j = j + 1 + l = l + 1 ; mask[l] = chars[t[j]] ; t[j] = "" + end + n = n + len + end + return concat(mask) + end + + local function decodemask08(content,xsize,ysize,depth,colorspace) + local t, bpp, len = prepareimage(content,xsize,ysize,depth,colorspace,1) + local bpp2 = mask and (bpp + bpp) or bpp + local n = 1 + local m = len - 1 + for i=1,ysize do + local filter = t[n] + if filter == 0 then + elseif filter == 1 then + for j=n+bpp2,n+m,bpp do + t[j] = (t[j] + t[j-bpp]) % 256 + end + elseif filter == 2 then + for j=n+bpp,n+m,bpp do + t[j] = (t[j] + t[j-len]) % 256 + end + elseif filter == 3 then + local j = n + bpp + t[j] = (t[j] + idiv(t[j-len],2)) % 256 + for j=n+bpp2,n+m,bpp do + t[j] = (t[j] + idiv(t[j-bpp] + t[j-len],2)) % 256 + end + elseif filter == 4 then + local j = n + bpp + local p = j - len + local b = t[p] + if b < 0 then + b = - b + end + if b > 0 then + t[j] = (t[j] + b) % 256 + end + for j=n+bpp2,n+m,bpp do + local p = j - len + local a = t[j-bpp] + local b = t[p] + local c = t[p-bpp] + local pa = b - c + local pb = a - c + local pc = pa + pb + if pa < 0 then pa = - pa end + if pb < 0 then pb = - pb end + if pc < 0 then pc = - pc end + t[j] = (t[j] + ((pa <= pb and pa <= pc and a) or (pb <= pc and b) or c)) % 256 + end + end + n = n + len + end + local mask = filtermask08(xsize,ysize,t,bpp,len,1) + return convert(t), mask + end + + local function decodemask16(content,xsize,ysize,depth,colorspace) + local t, bpp, len = prepareimage(content,xsize,ysize,depth,colorspace,1) + local bpp2 = bpp + bpp + local n = 1 + local m = len - 1 + for i=1,ysize do + local filter = t[n] + if filter == 0 then + elseif filter == 1 then + for j=n+bpp2,n+m,bpp do + local k = j - 1 + t[j] = (t[j] + t[j-bpp]) % 256 + t[k] = (t[k] + t[k-bpp]) % 256 + end + elseif filter == 2 then + for j=n+bpp,n+m,bpp do + local k = j - 1 + t[j] = (t[j] + t[j-len]) % 256 + t[k] = (t[k] + t[k-len]) % 256 + end + elseif filter == 3 then + local j = n + bpp + local k = j - 1 + t[j] = (t[j] + idiv(t[j-len],2)) % 256 + t[k] = (t[k] + idiv(t[k-len],2)) % 256 + for j=n+bpp2,n+m,bpp do + local k = j - 1 + t[j] = (t[j] + idiv(t[j-bpp] + t[j-len],2)) % 256 + t[k] = (t[k] + idiv(t[k-bpp] + t[k-len],2)) % 256 + end + elseif filter == 4 then + for i=-1,0 do + local j = n + bpp + i + local p = j - len + local b = t[p] + if b < 0 then + b = - b + end + if b > 0 then + t[j] = (t[j] + b) % 256 + end + for j=n+i+bpp2,n+i+m,bpp do + local p = j - len + local a = t[j-bpp] + local b = t[p] + local c = t[p-bpp] + local pa = b - c + local pb = a - c + local pc = pa + pb + if pa < 0 then pa = - pa end + if pb < 0 then pb = - pb end + if pc < 0 then pc = - pc end + t[j] = (t[j] + ((pa <= pb and pa <= pc and a) or (pb <= pc and b) or c)) % 256 + end + end + end + n = n + len + end + local mask = filtermask16(xsize,ysize,t,bpp,len,1) + return convert(t), mask + end + + local function full(t,k) local v = "\xFF" t[k] = v return v end + + local function create(content,palette,transparent,xsize,ysize,colordepth,colorspace) + if palette then + -- + local s = openstring(transparent) + local n = #transparent + local r = { } + for i=0,n-1 do + r[i] = readstring(s,1) + end + setmetatableindex(r,full) + -- + local c = zlib.decompress(content) + local s = openstring(c) + -- + local o = { } + local len = ceil(xsize*colordepth/8) + 1 + local m = len - 1 + local u = setmetatableindex(zero) + -- + for i=1,ysize do + local t = readbytetable(s,len) + local k = (i-1) * xsize + local filter = t[1] + if filter == 0 then + elseif filter == 1 then + for j=3,len do + t[j] = (t[j] + t[j-1]) % 256 + end + elseif filter == 2 then + for j=2,len do + t[j] = (t[j] + u[j]) % 256 + end + elseif filter == 3 then + local j = 2 + t[j] = (t[j] + idiv(u[j],2)) % 256 + for j=3,len do + t[j] = (t[j] + idiv(t[j-1] + u[j],2)) % 256 + end + elseif filter == 4 then + local j = 2 + local p = j - len + local b = t[p] + if b < 0 then + b = - b + end + if b > 0 then + t[j] = (t[j] + b) % 256 + end + for j=3,len do + local p = j - len + local a = t[j-1] + local b = t[p] + local c = t[p-1] + local pa = b - c + local pb = a - c + local pc = pa + pb + if pa < 0 then pa = - pa end + if pb < 0 then pb = - pb end + if pc < 0 then pc = - pc end + t[j] = (t[j] + ((pa <= pb and pa <= pc and a) or (pb <= pc and b) or c)) % 256 + end + end + if colordepth == 8 then + for j=2,len do + local v = t[j] + k = k + 1 ; o[k] = r[v] or "\xFF" + end + elseif colordepth == 4 then + for j=2,len do + local v = t[j] + k = k + 1 ; o[k] = r[band(rshift(v,4),0x0F)] + k = k + 1 ; o[k] = r[band(rshift(v,0),0x0F)] + end + elseif colordepth == 2 then + for j=2,len do + local v = t[j] + k = k + 1 ; o[k] = r[band(rshift(v,6),0x03)] + k = k + 1 ; o[k] = r[band(rshift(v,4),0x03)] + k = k + 1 ; o[k] = r[band(rshift(v,2),0x03)] + k = k + 1 ; o[k] = r[band(rshift(v,0),0x03)] + end + else + for j=2,len do + local v = t[j] + k = k + 1 ; o[k] = r[band(rshift(v,7),0x01)] + k = k + 1 ; o[k] = r[band(rshift(v,6),0x01)] + k = k + 1 ; o[k] = r[band(rshift(v,5),0x01)] + k = k + 1 ; o[k] = r[band(rshift(v,4),0x01)] + k = k + 1 ; o[k] = r[band(rshift(v,3),0x01)] + k = k + 1 ; o[k] = r[band(rshift(v,2),0x01)] + k = k + 1 ; o[k] = r[band(rshift(v,2),0x01)] + k = k + 1 ; o[k] = r[band(rshift(v,1),0x01)] + end + end + u = t + end + return concat(o,"",1,ysize * xsize) + end + end + + local alwaysdecode = false + + directives.register("graphics.png.decode", function(v) + alwaysdecode = v + end) + + function injectors.png(specification) + if specification.error then + return + end + local filename = specification.filename + if not filename then + return + end + local colorspace = specification.colorspace + if not colorspace then + return + end + local interlace = specification.interlace or 0 + if interlace == 1 then + interlace = true + elseif interlace == 0 then + interlace = false + else + report_png("unknown interlacing %i",interlace) + return + end + local tables = specification.tables + if not tables then + return + end + local idat = tables.idat + if not idat then + return + end + local pngfile = io.open(filename,"rb") + if not pngfile then + return + end + local content = idat(pngfile,true) + tables.idat = false + -- + -- if tables.gama then + -- report_png("ignoring gamma correction") + -- end + -- + local xsize = specification.xsize + local ysize = specification.ysize + local colordepth = specification.colordepth or 8 + local mask = false + local transparent = false + local palette = false + local colors = 1 + if colorspace == 0 then -- gray | image b + colorspace = "DeviceGray" + transparent = true + elseif colorspace == 2 then -- rgb | image c + colorspace = "DeviceRGB" + colors = 3 + transparent = true + elseif colorspace == 3 then -- palette | image c+i + colorspace = "DeviceRGB" + palette = true + transparent = true + elseif colorspace == 4 then -- gray | alpha | image b + colorspace = "DeviceGray" + mask = true + elseif colorspace == 6 then -- rgb | alpha | image c + colorspace = "DeviceRGB" + colors = 3 + mask = true + else + report_png("unknown colorspace %i",colorspace) + return + end + -- + if transparent then + local trns = tables.trns + if trns then + transparent = trns(pngfile,true) + if transparent == "" then + transparent = false + end + tables.trns = false + else + transparent = false + end + end + -- + local decode = alwaysdecode + local major = pdfmajorversion() + local minor = pdfminorversion() + if major > 1 then + -- we're okay + elseif minor < 5 and colordepth == 16 then + report_png("16 bit colordepth not supported in pdf < 1.5") + return + elseif minor < 4 and (mask or transparent) then + report_png("alpha channels not supported in pdf < 1.4") + return + elseif minor < 2 then + decode = true + end + -- + -- todo: compresslevel (or delegate) + -- + if palette then + local plte = tables.plte + if plte then + palette = plte(pngfile,true) + if palette == "" then + palette = false + end + tables.plte = false + else + palette = false + end + end + -- + if interlace then + local r, p = deinterlace(content,xsize,ysize,colordepth,colorspace,palette,mask) + if not r then + return + end + if p then + colordepth = p + end + if mask then + local bpp = (colordepth == 16 and 2 or 1) * ((colorspace == "DeviceRGB" and 3 or 1) + 1) + local len = bpp * xsize -- + 1 + if colordepth == 8 then -- bpp == 1 + mask = filtermask08(xsize,ysize,r,bpp,len,0) + elseif colordepth == 16 then -- bpp == 2 + mask = filtermask16(xsize,ysize,r,bpp,len,0) + else + report_png("mask can't be split from the image") + return + end + end + decode = true + content = convert(r) + content = zlib.compress(content) + elseif mask then + local decoder + if colordepth == 8 then + decoder = decodemask08 + elseif colordepth == 16 then + decoder = decodemask16 + end + if not decoder then + report_png("mask can't be split from the image") + return + end + content = zlib.decompress(content) + content, mask = decoder(content,xsize,ysize,colordepth,colorspace) + content = zlib.compress(content) + decode = false + elseif transparent then + if palette then + mask = create(content,palette,transparent,xsize,ysize,colordepth,colorspace) + else + pallette = false + end + elseif decode then + local r, p = decompose(content,xsize,ysize,colordepth,colorspace,palette) + if not r then + return + end + if p then + colordepth = p + end + content = convert(r) + content = zlib.compress(content) + end + if palette then + palette = pdfarray { + pdfconstant("Indexed"), + pdfconstant("DeviceRGB"), + idiv(#palette,3), + pdfreference(pdfflushstreamobject(palette)), + } + end + pngfile:close() + local xobject = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Image"), + BBox = pdfarray { 0, 0, xsize, ysize }, + Width = xsize, + Height = ysize, + BitsPerComponent = colordepth, + Filter = pdfconstant("FlateDecode"), + ColorSpace = palette or pdfconstant(colorspace), + Length = #content, + } + if mask then + local d = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Image"), + Width = xsize, + Height = ysize, + BitsPerComponent = palette and 8 or colordepth, + ColorSpace = pdfconstant("DeviceGray"), + } + xobject.SMask = pdfreference(pdfflushstreamobject(mask,d())) + end + if not decode then + xobject.DecodeParms = pdfdictionary { + Colors = colors, + Columns = xsize, + BitsPerComponent = colordepth, + Predictor = 15, + } + end + if attributes then + -- todo: add attributes to d + end + if trace then + report_png("%s: width %i, height %i, colordepth: %i, size: %i, palette %l, mask: %l, transparent %l, decode %l",filename,xsize,ysize,colordepth,#content,palette,mask,transparent,decode) + end + return newimage { + bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate + nolength = true, + nobbox = true, + notype = true, + stream = content, + attr = xobject(), + } + end + +end + +do + + local function pack(specification,what) + local t = { } + local n = 0 + local s = specification.colorspace + local d = specification.data + local x = specification.xsize + local y = specification.ysize + if what == "mask" then + d = specification.mask + s = 1 + end + if s == 1 then + for i=1,y do + local r = d[i] + for j=1,x do + n = n + 1 ; t[n] = chars[r[j]] + end + end + elseif s == 2 then + for i=1,y do + local r = d[i] + for j=1,x do + local c = r[j] + n = n + 1 ; t[n] = chars[c[1]] + n = n + 1 ; t[n] = chars[c[2]] + n = n + 1 ; t[n] = chars[c[3]] + end + end + elseif s == 3 then + for i=1,y do + local r = d[i] + for j=1,x do + local c = r[j] + n = n + 1 ; t[n] = chars[c[1]] + n = n + 1 ; t[n] = chars[c[2]] + n = n + 1 ; t[n] = chars[c[3]] + n = n + 1 ; t[n] = chars[c[4]] + end + end + end + return concat(t) + end + + function injectors.bitmap(specification) + local data = specification.data + if not data then + return + end + local xsize = specification.xsize or 0 + local ysize = specification.ysize or 0 + if xsize == 0 or ysize == 0 then + return + end + local colorspace = specification.colorspace or 1 + if colorspace == 1 then + colorspace = "DeviceGray" + elseif colorspace == 2 then + colorspace = "DeviceRGB" + elseif colorspace == 3 then + colorspace = "DeviceCMYK" + end + local colordepth = (specification.colordepth or 2) == 16 or 8 + local content = pack(specification,"data") + local mask = specification.mask + local xobject = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Image"), + BBox = pdfarray { 0, 0, xsize, ysize }, + Width = xsize, + Height = ysize, + BitsPerComponent = colordepth, + ColorSpace = pdfconstant(colorspace), + Length = #content, -- specification.length + } + if mask then + local d = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Image"), + Width = xsize, + Height = ysize, + BitsPerComponent = colordepth, + ColorSpace = pdfconstant("DeviceGray"), + } + xobject.SMask = pdfreference(pdfflushstreamobject(pack(specification,"mask"),d())) + end + return newimage { + bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate + -- nolength = true, + nobbox = true, + notype = true, + stream = content, + attr = xobject(), + } + end + +end diff --git a/tex/context/base/mkiv/pack-com.mkiv b/tex/context/base/mkiv/pack-com.mkiv index b69f812e5..badda0127 100644 --- a/tex/context/base/mkiv/pack-com.mkiv +++ b/tex/context/base/mkiv/pack-com.mkiv @@ -437,10 +437,10 @@ \nointerlineskip % indeed \combinationparameter\c!inbetween \global\c_pack_combinations_x\c_pack_combinations_max - \globallet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_yes + \glet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_yes \else \global\setbox\b_pack_combinations_captions\emptybox - \globallet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_nop + \glet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_nop \fi}% \pack_combinations_flush_captions_indeed \crcr} diff --git a/tex/context/base/mkiv/pack-lyr.mkiv b/tex/context/base/mkiv/pack-lyr.mkiv index 99a0dfb2a..e7070cfde 100644 --- a/tex/context/base/mkiv/pack-lyr.mkiv +++ b/tex/context/base/mkiv/pack-lyr.mkiv @@ -293,8 +293,8 @@ {\setbox\b_layers\emptybox \d_pack_layers_x_position\p_pack_layers_sx\dimexpr\p_pack_layers_x\relax \d_pack_layers_y_position\p_pack_layers_sy\dimexpr\p_pack_layers_y\relax - \globallet\lastlayerxpos\!!zeropoint - \globallet\lastlayerypos\!!zeropoint + \glet\lastlayerxpos\!!zeropoint + \glet\lastlayerypos\!!zeropoint \doifinset\v!bottom\p_pack_layers_corner\pack_layers_set_bottom_positions \doifinset\v!right \p_pack_layers_corner\pack_layers_set_right_positions \doifinset\v!middle\p_pack_layers_corner\pack_layers_set_middle_positions diff --git a/tex/context/base/mkiv/page-lin.mkvi b/tex/context/base/mkiv/page-lin.mkvi index 4348d6770..6470a8094 100644 --- a/tex/context/base/mkiv/page-lin.mkvi +++ b/tex/context/base/mkiv/page-lin.mkvi @@ -275,8 +275,8 @@ \fi\fi\fi \fi \the\beforeeverylinenumbering - \globallet\page_postprocessors_page \page_postprocessors_linenumbers_page - \globallet\page_postprocessors_column\page_postprocessors_linenumbers_column + \glet\page_postprocessors_page \page_postprocessors_linenumbers_page + \glet\page_postprocessors_column\page_postprocessors_linenumbers_column \global\settrue\page_postprocessors_needed_box % see core-rul.mkiv \ifcase\c_page_lines_mode\relax \page_lines_start_update % continue diff --git a/tex/context/base/mkiv/page-set.mkiv b/tex/context/base/mkiv/page-set.mkiv index f2755195a..dd145b322 100644 --- a/tex/context/base/mkiv/page-set.mkiv +++ b/tex/context/base/mkiv/page-set.mkiv @@ -487,7 +487,7 @@ \let\OTRSETbalht\zeropoint \def\OTRSETreducegridbox % for the moment no difference between methods - {\globallet\OTRSETbalht\zeropoint + {\glet\OTRSETbalht\zeropoint \ifcase\OTRSETbalancemethod % no balancing \else @@ -578,7 +578,7 @@ \else \page_otr_construct_and_shipout\box\OTRfinalpagebox\zerocount % three arguments \fi \fi - \globallet\OTRSETbalht\zeropoint + \glet\OTRSETbalht\zeropoint \egroup \fi} @@ -1624,12 +1624,12 @@ \ifnum\columnsetlevel=\plusone \bgroup \saveinterlinespace - \globallet\columnsetpage\!!plusone + \glet\columnsetpage\!!plusone \def\currentcolumnset{#2}% \insidecolumnstrue % will be different flag in addition \setupoutputroutine[\s!columnset]% \doifelsenothing{#1} - {\globallet\OTRSETlist\s!default} + {\glet\OTRSETlist\s!default} {\xdef\OTRSETlist{#1}}% \OTRSETstartnextpage \OTRSETassignwidths @@ -1659,7 +1659,7 @@ \global\setbox\OTRfinalpagebox\OTRSETmakegridbox \ht\OTRfinalpagebox\textheight % signals output that there is content \OTRSETdofinaloutput - \globallet\OTRSETbalht\zeropoint + \glet\OTRSETbalht\zeropoint \egroup} {}} diff --git a/tex/context/base/mkiv/scrn-fld.mkvi b/tex/context/base/mkiv/scrn-fld.mkvi index 41d117480..7710a32dc 100644 --- a/tex/context/base/mkiv/scrn-fld.mkvi +++ b/tex/context/base/mkiv/scrn-fld.mkvi @@ -480,7 +480,7 @@ \let\resetfields\relax -\def\scrn_field_load_scripts{\useJSscripts[fld]\globallet\scrn_field_load_scripts\relax} +\def\scrn_field_load_scripts{\useJSscripts[fld]\glet\scrn_field_load_scripts\relax} \newconditional\fieldlabelshown \newconditional\fieldframeshown diff --git a/tex/context/base/mkiv/spac-pag.mkiv b/tex/context/base/mkiv/spac-pag.mkiv index 89a5ce36d..9adc591ed 100644 --- a/tex/context/base/mkiv/spac-pag.mkiv +++ b/tex/context/base/mkiv/spac-pag.mkiv @@ -170,9 +170,9 @@ \fi \ifpagechanged \letgvalue{\??pagechanges#2:#1}\m_spac_pagestates_realpage - \globallet\lastchangedpage\m_spac_pagestates_realpage + \glet\lastchangedpage\m_spac_pagestates_realpage \else - \globallet\lastchangedpage\realfolio + \glet\lastchangedpage\realfolio \fi} \def\changedpagestate#1#2% diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex 31155292e..20a7f18e1 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex b1227d969..b48b2651a 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/strc-con.mkvi b/tex/context/base/mkiv/strc-con.mkvi index 0e5f3d8a5..d67307ba7 100644 --- a/tex/context/base/mkiv/strc-con.mkvi +++ b/tex/context/base/mkiv/strc-con.mkvi @@ -1016,9 +1016,9 @@ \fi \fi \fi \ifx\currentconstructionlist\empty - \globallet\currentconstructionlist\currentconstructiontitle + \glet\currentconstructionlist\currentconstructiontitle \fi - \globallet\currentconstructioncoding\s!tex + \glet\currentconstructioncoding\s!tex \fi % \ifx\currentconstructiontitle\v!none % will become obsolete diff --git a/tex/context/base/mkiv/strc-flt.mkvi b/tex/context/base/mkiv/strc-flt.mkvi index 805a6edc7..28fa950c7 100644 --- a/tex/context/base/mkiv/strc-flt.mkvi +++ b/tex/context/base/mkiv/strc-flt.mkvi @@ -425,7 +425,7 @@ %D {\global\advance\c_strc_floats_n\plusone %D \xdef\strc_float_realpage{\datasetvariable\s!float{\number\c_strc_floats_n}\s!page}% %D \ifx\strc_float_realpage\empty -%D \globallet\strc_float_realpage\realpageno % \realfolio +%D \glet\strc_float_realpage\realpageno % \realfolio %D \fi} %D \stoptyping %D @@ -444,7 +444,7 @@ {\global\advance\c_strc_floats_n\plusone \xdef\strc_float_realpage{\pagestaterealpage\s!float{\number\c_strc_floats_n}}% \ifx\strc_float_realpage\empty - \globallet\strc_float_realpage\realpageno % \realfolio + \glet\strc_float_realpage\realpageno % \realfolio \fi} %D test case: @@ -955,9 +955,9 @@ \def\strc_floats_place_packaged_boxes_indeed#userdata% {\bgroup \ifconditional\usesamefloatnumber - \globallet\currentfloatnumber \previousfloatnumber - \globallet\currentfloatattribute \empty - \globallet\currentfloatsynchronize\relax + \glet\currentfloatnumber \previousfloatnumber + \glet\currentfloatattribute \empty + \glet\currentfloatsynchronize\relax \else \edef\currentfloatcounter{\namedcounterparameter\currentfloat\s!name}% \edef\currentfloatgroup {\floatcaptionparameter\c!group}% @@ -989,10 +989,10 @@ \s!hasnumber=\ifnofloatnumber \v!no\else\v!yes\fi,% \s!hastitle=\ifemptyfloatcaption\v!no\else\v!yes\fi]% [#userdata]% - \globallet\previousfloatnumber \m_strc_counters_last_registered_index - \globallet\currentfloatnumber \m_strc_counters_last_registered_index - \globallet\currentfloatattribute \m_strc_counters_last_registered_attribute - \globallet\currentfloatsynchronize\m_strc_counters_last_registered_synchronize + \glet\previousfloatnumber \m_strc_counters_last_registered_index + \glet\currentfloatnumber \m_strc_counters_last_registered_index + \glet\currentfloatattribute \m_strc_counters_last_registered_attribute + \glet\currentfloatsynchronize\m_strc_counters_last_registered_synchronize \fi % \global\setfalse\usesamefloatnumber % one shot diff --git a/tex/context/base/mkiv/strc-mat.mkiv b/tex/context/base/mkiv/strc-mat.mkiv index 89912d904..0b80a26cd 100644 --- a/tex/context/base/mkiv/strc-mat.mkiv +++ b/tex/context/base/mkiv/strc-mat.mkiv @@ -208,9 +208,9 @@ \c!reference=#1,\c!title=\namedformulaentry,\c!bookmark=]% [#2]% \glet\namedformulaentry\empty % \relax - \globallet#3\m_strc_counters_last_registered_index - \globallet#4\m_strc_counters_last_registered_synchronize - \globallet#5\m_strc_counters_last_registered_attribute} + \glet#3\m_strc_counters_last_registered_index + \glet#4\m_strc_counters_last_registered_synchronize + \glet#5\m_strc_counters_last_registered_attribute} % modes: 0=unset, 1=forced, 2=none, 3=reference diff --git a/tex/context/base/mkiv/strc-not.mkvi b/tex/context/base/mkiv/strc-not.mkvi index 403247b9c..3ce01ef34 100644 --- a/tex/context/base/mkiv/strc-not.mkvi +++ b/tex/context/base/mkiv/strc-not.mkvi @@ -456,7 +456,7 @@ \edef\currentnotenumber{\clf_storenote{\currentnote}\currentconstructionlistentry}% \settrue\processingnote \ifconditional\c_strc_notes_skip - \globallet\lastnotesymbol\strc_notes_inject_symbol_nop + \glet\lastnotesymbol\strc_notes_inject_symbol_nop \else \iftypesettinglines % otherwise problems with \type <crlf> {xxx} \ignorelines % makes footnotes work in \startlines ... \stoplines @@ -465,7 +465,7 @@ \strc_notes_inject_symbol_yes \else \unskip\unskip - \globallet\lastnotesymbol\strc_notes_inject_symbol_yes + \glet\lastnotesymbol\strc_notes_inject_symbol_yes \fi \fi \ifconditional\postponingnotes % todo: per note class @@ -734,7 +734,7 @@ \dostoptagged \egroup \endgroup - \globallet\lastnotesymbol\relax} + \glet\lastnotesymbol\relax} \unexpanded\def\strc_notes_inject_dummy % temp hack {\removeunwantedspaces @@ -745,7 +745,7 @@ \fi \nobreak \hpack to .5\emwidth{}% - \globallet\lastnotesymbol\relax} + \glet\lastnotesymbol\relax} \unexpanded\def\strc_notes_inject_separator % patch by WS due to request on list {\edef\p_textseparator{\noteparameter\c!textseparator}% diff --git a/tex/context/base/mkiv/strc-num.mkiv b/tex/context/base/mkiv/strc-num.mkiv index cca66a6f5..747df29a5 100644 --- a/tex/context/base/mkiv/strc-num.mkiv +++ b/tex/context/base/mkiv/strc-num.mkiv @@ -578,9 +578,9 @@ \xdef\currentstructurecomponentlist {#2\c!list}% \xmlstopraw \ifx\currentstructurecomponentlist\empty - \globallet\currentstructurecomponentlist\currentstructurecomponenttitle + \glet\currentstructurecomponentlist\currentstructurecomponenttitle \fi - \globallet\currentstructurecomponentcoding\s!xml + \glet\currentstructurecomponentcoding\s!xml \else \ifx\currentstructurecomponentexpansion\v!yes \xdef\currentstructurecomponenttitle {#2\c!title}% @@ -600,9 +600,9 @@ \fi \fi \fi \ifx\currentstructurecomponentlist\empty - \globallet\currentstructurecomponentlist\currentstructurecomponenttitle + \glet\currentstructurecomponentlist\currentstructurecomponenttitle \fi - \globallet\currentstructurecomponentcoding\s!tex + \glet\currentstructurecomponentcoding\s!tex \fi % \setnextinternalreference diff --git a/tex/context/base/mkiv/strc-pag.mkiv b/tex/context/base/mkiv/strc-pag.mkiv index 949806c82..01361e2c5 100644 --- a/tex/context/base/mkiv/strc-pag.mkiv +++ b/tex/context/base/mkiv/strc-pag.mkiv @@ -263,7 +263,7 @@ \def\currentpage{\the\realpageno}% rather useless \appendtoks - \ifnum\realpageno>\lastpage \globallet\lastpage\lastrealpage \fi + \ifnum\realpageno>\lastpage \glet\lastpage\lastrealpage \fi \to \everyinitializepagecounters % States: diff --git a/tex/context/base/mkiv/strc-ref.mkvi b/tex/context/base/mkiv/strc-ref.mkvi index 0ae2cfccc..47719ffe2 100644 --- a/tex/context/base/mkiv/strc-ref.mkvi +++ b/tex/context/base/mkiv/strc-ref.mkvi @@ -212,14 +212,14 @@ \xmlstartraw \xdef\currentreferencedata{#text}% data, no text else conflict \xmlstopraw - \globallet\currentreferencecoding\s!xml + \glet\currentreferencecoding\s!xml \else \ifx\currentreferenceexpansion\v!yes \xdef\currentreferencedata{#text}% \else \xdef\currentreferencedata{\detokenize{#text}}% \fi - \globallet\currentreferencecoding\s!tex + \glet\currentreferencecoding\s!tex \fi % beware, the structures.references.set writes a \setnextinternalreference diff --git a/tex/context/base/mkiv/strc-reg.mkiv b/tex/context/base/mkiv/strc-reg.mkiv index 21779f479..559e1bd42 100644 --- a/tex/context/base/mkiv/strc-reg.mkiv +++ b/tex/context/base/mkiv/strc-reg.mkiv @@ -176,33 +176,33 @@ \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}% \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}% \xmlstopraw - \globallet\currentregistercoding\s!xml} + \glet\currentregistercoding\s!xml} \def\strc_registers_register_page_expand_yes_entries {\xdef\currentregisterentriesa{\registerparameter{\c!entries:1}}% \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}% \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}% - \globallet\currentregistercoding\s!tex} + \glet\currentregistercoding\s!tex} \def\strc_registers_register_page_expand_nop_entries {\xdef\currentregisterentriesa{\detokenizedregisterparameter{\c!entries:1}}% \xdef\currentregisterentriesb{\detokenizedregisterparameter{\c!entries:2}}% \xdef\currentregisterentriesc{\detokenizedregisterparameter{\c!entries:3}}% - \globallet\currentregistercoding\s!tex} + \glet\currentregistercoding\s!tex} \def\strc_registers_register_page_expand_xml {\xmlstartraw \xdef\currentregisterentries{\registerparameter\c!entries}% \xmlstopraw - \globallet\currentregistercoding\s!xml} + \glet\currentregistercoding\s!xml} \def\strc_registers_register_page_expand_yes {\xdef\currentregisterentries{\registerparameter\c!entries}% - \globallet\currentregistercoding\s!tex} + \glet\currentregistercoding\s!tex} \def\strc_registers_register_page_expand_nop {\xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}% - \globallet\currentregistercoding\s!tex} + \glet\currentregistercoding\s!tex} \def\strc_registers_register_page_expand_xml_keys {\xmlstartraw @@ -434,14 +434,14 @@ \xmlstartraw \xdef\currentregisterentries{\registerparameter\c!entries}% \xmlstopraw - \globallet\currentregistercoding\s!xml + \glet\currentregistercoding\s!xml \else \ifx\currentregisterexpansion\v!yes \xdef\currentregisterentries{\registerparameter\c!entries}% \else \xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}% \fi - \globallet\currentregistercoding\s!tex + \glet\currentregistercoding\s!tex \fi % I hate this kind of mess ... but it's a user request. \ifx\currentregisterentries\empty @@ -524,7 +524,7 @@ \xdef\currentregisterentries{\detokenize{#3}}% not ok yet \xdef\currentregisterseeword{\detokenize{#4}}% not ok yet \xmlstopraw - \globallet\currentregistercoding\s!xml + \glet\currentregistercoding\s!xml \else \ifx\currentregisterexpansion\v!yes \xdef\currentregisterentries{#3}% not ok yet @@ -533,7 +533,7 @@ \xdef\currentregisterentries{\detokenize{#3}}% not ok yet \xdef\currentregisterseeword{\detokenize{#4}}% not ok yet \fi - \globallet\currentregistercoding\s!tex + \glet\currentregistercoding\s!tex \fi \setnextinternalreference % we could consider storing register entries in list diff --git a/tex/context/base/mkiv/strc-sec.mkiv b/tex/context/base/mkiv/strc-sec.mkiv index 8f6038da7..cff73718a 100644 --- a/tex/context/base/mkiv/strc-sec.mkiv +++ b/tex/context/base/mkiv/strc-sec.mkiv @@ -116,7 +116,7 @@ % \settrialtypesetting \the\everypreroll \nodestostring\tempstring{#1}% - \globallet\currentstructurebookmark\tempstring + \glet\currentstructurebookmark\tempstring \endgroup} % zeros: @@ -156,9 +156,9 @@ \strc_sectioning_autobookmark\currentstructuretitle \fi \fi \fi \ifx\currentstructurelist\empty - \globallet\currentstructurelist\currentstructuretitle + \glet\currentstructurelist\currentstructuretitle \fi - \globallet\currentstructurecoding\s!xml + \glet\currentstructurecoding\s!xml \else \ifx\currentstructureexpansion\v!yes \xdef\currentstructuretitle {\structureparameter\c!title}% @@ -185,9 +185,9 @@ \fi \fi \fi \ifx\currentstructurelist\empty - \globallet\currentstructurelist\currentstructuretitle + \glet\currentstructurelist\currentstructuretitle \fi - \globallet\currentstructurecoding\s!tex + \glet\currentstructurecoding\s!tex \fi \setnextinternalreference \storeinternalreference\currentstructurename{\the\locationcount}% @@ -1206,7 +1206,7 @@ \else \strc_sectioning_check_layout \fi - \globallet\previoushead\currenthead} + \glet\previoushead\currenthead} \def\strc_sectioning_handle_page_yes {\ifconditional\c_strc_sectioning_ignore_page @@ -1230,7 +1230,7 @@ \fi \global\c_strc_sectioning_preceding_level\currentheadlevel \fi - \globallet\previoushead\currenthead} + \glet\previoushead\currenthead} \unexpanded\def\strc_sectioning_prevent_page_break#1% see strc-con {\ifconditional\c_strc_sectioning_auto_break diff --git a/tex/context/base/mkiv/strc-syn.mkiv b/tex/context/base/mkiv/strc-syn.mkiv index 1fb079f04..7f71e88f5 100644 --- a/tex/context/base/mkiv/strc-syn.mkiv +++ b/tex/context/base/mkiv/strc-syn.mkiv @@ -114,14 +114,14 @@ \xmlstartraw \xdef#2{#4}% \xmlstopraw - \globallet#3\s!xml + \glet#3\s!xml \else \ifx#1\v!yes \xdef#2{#4}% \else \xdef#2{\detokenize{#4}}% \fi - \globallet#3\s!tex + \glet#3\s!tex \fi} %D We now use a simple list variant: diff --git a/tex/context/base/mkiv/symb-imp-mvs.mkiv b/tex/context/base/mkiv/symb-imp-mvs.mkiv index 9902fc9e8..f6a38214f 100644 --- a/tex/context/base/mkiv/symb-imp-mvs.mkiv +++ b/tex/context/base/mkiv/symb-imp-mvs.mkiv @@ -254,10 +254,16 @@ \stopsymbolset -%D \showsymbolset[astronomic] -%D \showsymbolset[zodiac] -%D \showsymbolset[europe] -%D \showsymbolset[martinvogel 1] -%D \showsymbolset[martinvogel 2] +\continueifinputfile{symb-imp-mvs.mkiv} -\endinput +\usemodule[article-basic] + +\starttext + +\startsubject[title={Astronomic}] \showsymbolset[astronomic] \stopsubject +\startsubject[title={Zodiac}] \showsymbolset[zodiac] \stopsubject +\startsubject[title={Europe}] \showsymbolset[europe] \stopsubject +\startsubject[title={Martinvogel 1}] \showsymbolset[martinvogel 1] \stopsubject +\startsubject[title={Martinvogel 2}] \showsymbolset[martinvogel 2] \stopsubject + +\stoptext diff --git a/tex/context/base/mkiv/syst-aux.mkiv b/tex/context/base/mkiv/syst-aux.mkiv index a23563f3c..9c959a105 100644 --- a/tex/context/base/mkiv/syst-aux.mkiv +++ b/tex/context/base/mkiv/syst-aux.mkiv @@ -594,10 +594,6 @@ %D tokens will save us some $300\times4=1200$ bytes of format file on a 32~bit %D system. Not that it matters much today. This shortcut is already defined: -\ifdefined\glet\else - \unexpanded\def\glet{\global\let} -\fi - \let\globallet\glet %D \macros diff --git a/tex/context/base/mkiv/syst-ini.mkiv b/tex/context/base/mkiv/syst-ini.mkiv index 10c1fa113..f7b73a30e 100644 --- a/tex/context/base/mkiv/syst-ini.mkiv +++ b/tex/context/base/mkiv/syst-ini.mkiv @@ -610,10 +610,6 @@ %D A few shortcuts: -\ifdefined\glet \else - \normalprotected\def\glet{\global\let} -\fi - \normalprotected\def\udef {\normalprotected\def } \normalprotected\def\ugdef{\normalprotected\gdef} \normalprotected\def\uedef{\normalprotected\edef} @@ -940,12 +936,12 @@ % \bgroup % \catcode`\^^M=\activecatcode% % \gdef\obeylines{\catcode`\^^M\activecatcode \let^^M\par}% -% \global\let^^M\par% +% \glet^^M\par% % \egroup % % \bgroup % \gdef\obeyspaces{\catcode`\ \activecatcode}% -% \obeyspaces\global\let =\space% +% \obeyspaces\glet =\space% % \egroup \def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\par} @@ -1252,10 +1248,6 @@ \let\normalstartdmath \Ustartdisplaymath \let\normalstopdmath \Ustopdisplaymath -%D For now: - -\ifdefined\glet \else \normalprotected\def\glet{\global\let} \fi - \ifdefined\protrusionboundary \else \let\protrusionboundary\boundary \fi \ifdefined\wordboundary \else \let\wordboundary \noboundary \fi diff --git a/tex/context/base/mkiv/tabl-tab.mkiv b/tex/context/base/mkiv/tabl-tab.mkiv index 244ead530..631f29bc0 100644 --- a/tex/context/base/mkiv/tabl-tab.mkiv +++ b/tex/context/base/mkiv/tabl-tab.mkiv @@ -688,7 +688,7 @@ % extensions \newtableformatkey q% - {\letempty\!tqStyle + {\let\!tqStyle\empty \futurelet\!tnext\!tqTestForBracket} \newtableformatkey Q% @@ -1691,8 +1691,8 @@ \starttablenoalign \nobreak \tabl_table_set_action\tableunknownstate - \globalletempty\tabl_tables_check_auto_row - \globalletempty\tabl_tables_chuck_auto_row + \glet\tabl_tables_check_auto_row\empty + \glet\tabl_tables_chuck_auto_row\empty \global\currenttablecolumn\zerocount \stoptablenoalign} @@ -1816,21 +1816,21 @@ %D the last row. \unexpanded\def\tabl_table_AR - {\globallet\tabl_tables_check_auto_row\tabl_tables_check_auto_row_indeed - \globallet\tabl_tables_chuck_auto_row\tabl_tables_chuck_auto_row_indeed} + {\glet\tabl_tables_check_auto_row\tabl_tables_check_auto_row_indeed + \glet\tabl_tables_chuck_auto_row\tabl_tables_chuck_auto_row_indeed} \let\tabl_tables_check_auto_row\empty \let\tabl_tables_chuck_auto_row\empty \def\tabl_tables_check_auto_row_indeed - {\globallet\tabl_tables_check_auto_row\empty + {\glet\tabl_tables_check_auto_row\empty \ifnum\tableactionstate=\tablerulestate \FR\else \ifnum\tableactionstate=\tableunknownstate\FR\else \MR\fi\fi} \def\tabl_tables_chuck_auto_row_indeed - {\globalletempty\tabl_tables_check_auto_row - \globalletempty\tabl_tables_chuck_auto_row + {\glet\tabl_tables_check_auto_row\empty + \glet\tabl_tables_chuck_auto_row\empty \ifnum\tableactionstate=\tablerulestate \SR\else \ifnum\tableactionstate=\tableunknownstate\SR\else \LR\fi\fi} diff --git a/tex/context/base/mkiv/tabl-tbl.mkiv b/tex/context/base/mkiv/tabl-tbl.mkiv index 97a4f63c0..75839caed 100644 --- a/tex/context/base/mkiv/tabl-tbl.mkiv +++ b/tex/context/base/mkiv/tabl-tbl.mkiv @@ -2235,7 +2235,7 @@ % \def\tabulatedoHRfive % horizontal rule line (break untested) % {\starttabulatenoalign -% \globallet\dotabulateautoline\dotabulatelinerule +% \glet\dotabulateautoline\dotabulatelinerule % %\ifcase#1\or % todo: check what this does % \ifnum\noftabulatelines=\zerocount % \glet\dotabulateautoline\donothing diff --git a/tex/context/base/mkiv/typo-drp.mkiv b/tex/context/base/mkiv/typo-drp.mkiv index 371ea38d6..183925108 100644 --- a/tex/context/base/mkiv/typo-drp.mkiv +++ b/tex/context/base/mkiv/typo-drp.mkiv @@ -118,7 +118,7 @@ \kern\zeropoint % we need a node \p_text \endgroup - \globallet\typo_initial_handle\relax} + \glet\typo_initial_handle\relax} \let\typo_initial_handle\relax diff --git a/tex/context/base/mkiv/typo-fln.mkiv b/tex/context/base/mkiv/typo-fln.mkiv index 37348be29..533c197cd 100644 --- a/tex/context/base/mkiv/typo-fln.mkiv +++ b/tex/context/base/mkiv/typo-fln.mkiv @@ -91,7 +91,7 @@ \kern\zeropoint % we need a node % \hskip\zeropoint\s!plus\emwidth\relax % can be an option \endgroup - \globallet\typo_firstline_handle\relax} + \glet\typo_firstline_handle\relax} \let\typo_firstline_handle\relax diff --git a/tex/context/base/mkiv/util-sac.lua b/tex/context/base/mkiv/util-sac.lua index 09c3819c5..62ce6bc1c 100644 --- a/tex/context/base/mkiv/util-sac.lua +++ b/tex/context/base/mkiv/util-sac.lua @@ -21,6 +21,10 @@ function streams.open(filename,zerobased) return { f, 1, #f, zerobased or false } end +function streams.openstring(f,zerobased) + return { f, 1, #f, zerobased or false } +end + function streams.close() -- dummy end @@ -389,8 +393,32 @@ end if sio and sio.readcardinaltable then - streams.readcardinaltable = sio.readcardinaltable - streams.readintegertable = sio.readintegertable + local readcardinaltable = sio.readcardinaltable + local readintegertable = sio.readintegertable + + function utilities.streams.readcardinaltable(f,n,b) + local i = f[2] + local s = f[3] + local p = i + n * b + if p > s then + f[2] = s + 1 + else + f[2] = p + end + return readcardinaltable(f[1],i,n,b) + end + + function utilities.streams.readintegertable(f,n,b) + local i = f[2] + local s = f[3] + local p = i + n * b + if p > s then + f[2] = s + 1 + else + f[2] = p + end + return readintegertable(f[1],i,n,b) + end else @@ -400,11 +428,19 @@ else local readcardinal4 = streams.readcardinal4 function streams.readcardinaltable(f,n,b) + local i = f[2] + local s = f[3] + local p = i + n * b + if p > s then + f[2] = s + 1 + else + f[2] = p + end local t = { } - if b == 1 then for i=1,n do t[i] = readcardinal1(f) end - elseif b == 2 then for i=1,n do t[i] = readcardinal2(f) end - elseif b == 3 then for i=1,n do t[i] = readcardinal3(f) end - elseif b == 4 then for i=1,n do t[i] = readcardinal4(f) end end + if b == 1 then for i=1,n do t[i] = readcardinal1(f[1],i) end + elseif b == 2 then for i=1,n do t[i] = readcardinal2(f[1],i) end + elseif b == 3 then for i=1,n do t[i] = readcardinal3(f[1],i) end + elseif b == 4 then for i=1,n do t[i] = readcardinal4(f[1],i) end end return t end @@ -414,11 +450,19 @@ else local readinteger4 = streams.readinteger4 function streams.readintegertable(f,n,b) + local i = f[2] + local s = f[3] + local p = i + n * b + if p > s then + f[2] = s + 1 + else + f[2] = p + end local t = { } - if b == 1 then for i=1,n do t[i] = readinteger1(f) end - elseif b == 2 then for i=1,n do t[i] = readinteger2(f) end - elseif b == 3 then for i=1,n do t[i] = readinteger3(f) end - elseif b == 4 then for i=1,n do t[i] = readinteger4(f) end end + if b == 1 then for i=1,n do t[i] = readinteger1(f[1],i) end + elseif b == 2 then for i=1,n do t[i] = readinteger2(f[1],i) end + elseif b == 3 then for i=1,n do t[i] = readinteger3(f[1],i) end + elseif b == 4 then for i=1,n do t[i] = readinteger4(f[1],i) end end return t end diff --git a/tex/context/interface/mkii/keys-fr.xml b/tex/context/interface/mkii/keys-fr.xml index 5ab324b97..c5da3adca 100644 --- a/tex/context/interface/mkii/keys-fr.xml +++ b/tex/context/interface/mkii/keys-fr.xml @@ -1247,6 +1247,7 @@ <cd:constant name='textstyle' value='styletexte'/> <cd:constant name='textwidth' value='largeurtexte'/> <cd:constant name='threshold' value='threshold'/> + <cd:constant name='time' value='time'/> <cd:constant name='title' value='titre'/> <cd:constant name='titlecolor' value='couleurtitre'/> <cd:constant name='titlecommand' value='titlecommand'/> diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf Binary files differindex d8dc51e14..e1e1bc1cd 100644 --- a/tex/context/interface/mkiv/i-context.pdf +++ b/tex/context/interface/mkiv/i-context.pdf diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf Binary files differindex fac1c6288..b8ae1bd64 100644 --- a/tex/context/interface/mkiv/i-readme.pdf +++ b/tex/context/interface/mkiv/i-readme.pdf diff --git a/tex/context/modules/mkiv/m-format.mkiv b/tex/context/modules/mkiv/m-format.mkiv index f9dd348a4..3a0a5bebd 100644 --- a/tex/context/modules/mkiv/m-format.mkiv +++ b/tex/context/modules/mkiv/m-format.mkiv @@ -217,7 +217,7 @@ \doglobal\newcounter\formatlinesubcounter \reshapebox {\doglobal\increment\formatlinesubcounter} - \global\let\formatlinemaxcounter\formatlinesubcounter + \glet\formatlinemaxcounter\formatlinesubcounter \reshapebox {\doglobal\decrement\formatlinesubcounter \ifnum\formatlinesubcounter=\zerocount @@ -303,7 +303,7 @@ \doglobal\newcounter\formatlinesubcounter \reshapebox {\doglobal\increment\formatlinesubcounter}% - \global\let\formatlinemaxcounter\formatlinesubcounter + \glet\formatlinemaxcounter\formatlinesubcounter \reshapebox {\doglobal\decrement\formatlinesubcounter \ifnum\formatlinesubcounter=\zerocount diff --git a/tex/context/modules/mkiv/s-fonts-charts.mkiv b/tex/context/modules/mkiv/s-fonts-charts.mkiv index 50cd589e4..d8d0975de 100644 --- a/tex/context/modules/mkiv/s-fonts-charts.mkiv +++ b/tex/context/modules/mkiv/s-fonts-charts.mkiv @@ -169,36 +169,39 @@ \starttext - \showfontchart[filename=LucidaBrightOT.otf,page=yes] - \showfontchart[filename=LucidaBrightOT-Demi.otf,page=yes] - \showfontchart[filename=LucidaBrightOT-DemiItalic.otf,page=yes] - \showfontchart[filename=LucidaBrightOT-Italic.otf,page=yes] - - \showfontchart[filename=LucidaSansOT.otf,page=yes] - \showfontchart[filename=LucidaSansOT-Demi.otf,page=yes] - \showfontchart[filename=LucidaSansOT-DemiItalic.otf,page=yes] - \showfontchart[filename=LucidaSansOT-Italic.otf,page=yes] - - \showfontchart[filename=LucidaSansTypewriterOT.otf,page=yes] - \showfontchart[filename=LucidaSansTypewriterOT-Bold.otf,page=yes] - \showfontchart[filename=LucidaSansTypewriterOT-BoldOblique.otf,page=yes] - \showfontchart[filename=LucidaSansTypewriterOT-Oblique.otf,page=yes] - - \showfontchart[filename=LucidaConsoleDK.otf,page=yes] - \showfontchart[filename=LucidaConsoleDK-Bold.otf,page=yes] - \showfontchart[filename=LucidaConsoleDK-BoldItalic.otf,page=yes] - \showfontchart[filename=LucidaConsoleDK-Italic.otf,page=yes] - - \showfontchart[filename=LucidaGrandeMonoDK.otf,page=yes] - \showfontchart[filename=LucidaGrandeMonoDK-Bold.otf,page=yes] - \showfontchart[filename=LucidaGrandeMonoDK-BoldItalic.otf,page=yes] - \showfontchart[filename=LucidaGrandeMonoDK-Italic.otf,page=yes] - - \showfontchart[filename=LucidaBrightMathOT.otf,page=yes] - \showfontchart[filename=LucidaBrightMathOT-Demi.otf,page=yes] - - \showfontchart[filename=LucidaBlackletterOT.otf,page=yes] - \showfontchart[filename=LucidaCalligraphyOT.otf,page=yes] - \showfontchart[filename=LucidaHandwritingOT.otf,page=yes] +% \showfontchart[filename=veramono.ttf,page=yes] + \showfontchart[filename=CoelacanthSubhdHeavy.otf,page=yes] + +% \showfontchart[filename=LucidaBrightOT.otf,page=yes] +% \showfontchart[filename=LucidaBrightOT-Demi.otf,page=yes] +% \showfontchart[filename=LucidaBrightOT-DemiItalic.otf,page=yes] +% \showfontchart[filename=LucidaBrightOT-Italic.otf,page=yes] + +% \showfontchart[filename=LucidaSansOT.otf,page=yes] +% \showfontchart[filename=LucidaSansOT-Demi.otf,page=yes] +% \showfontchart[filename=LucidaSansOT-DemiItalic.otf,page=yes] +% \showfontchart[filename=LucidaSansOT-Italic.otf,page=yes] + +% \showfontchart[filename=LucidaSansTypewriterOT.otf,page=yes] +% \showfontchart[filename=LucidaSansTypewriterOT-Bold.otf,page=yes] +% \showfontchart[filename=LucidaSansTypewriterOT-BoldOblique.otf,page=yes] +% \showfontchart[filename=LucidaSansTypewriterOT-Oblique.otf,page=yes] + +% \showfontchart[filename=LucidaConsoleDK.otf,page=yes] +% \showfontchart[filename=LucidaConsoleDK-Bold.otf,page=yes] +% \showfontchart[filename=LucidaConsoleDK-BoldItalic.otf,page=yes] +% \showfontchart[filename=LucidaConsoleDK-Italic.otf,page=yes] + +% \showfontchart[filename=LucidaGrandeMonoDK.otf,page=yes] +% \showfontchart[filename=LucidaGrandeMonoDK-Bold.otf,page=yes] +% \showfontchart[filename=LucidaGrandeMonoDK-BoldItalic.otf,page=yes] +% \showfontchart[filename=LucidaGrandeMonoDK-Italic.otf,page=yes] + +% \showfontchart[filename=LucidaBrightMathOT.otf,page=yes] +% \showfontchart[filename=LucidaBrightMathOT-Demi.otf,page=yes] + +% \showfontchart[filename=LucidaBlackletterOT.otf,page=yes] +% \showfontchart[filename=LucidaCalligraphyOT.otf,page=yes] +% \showfontchart[filename=LucidaHandwritingOT.otf,page=yes] \stoptext diff --git a/tex/context/modules/mkiv/s-fonts-complete.mkiv b/tex/context/modules/mkiv/s-fonts-complete.mkiv index afdd79b4c..83aa708df 100644 --- a/tex/context/modules/mkiv/s-fonts-complete.mkiv +++ b/tex/context/modules/mkiv/s-fonts-complete.mkiv @@ -29,23 +29,36 @@ local descriptions = tfmdata.descriptions or { } local data = characters.data -- context.setuptabulate { header = "repeat" } - context.starttabulatehead() - NC() bold("unicode") - NC() bold("visual") - NC() bold("index") - NC() bold("glyph") - NC() bold("adobe") - NC() bold("context") - NC() NR() - context.stoptabulatehead() - context.starttabulate { "|l|c|l|p|p|p|" } + -- context.starttabulatehead() + -- NC() bold("unicode") + -- NC() bold("visual") + -- NC() bold("index") + -- NC() bold("tounicode") + -- NC() bold("unicodes") + -- NC() bold("glyph") + -- NC() bold("adobe") + -- NC() bold("context") + -- NC() NR() + -- context.stoptabulatehead() + context.starttabulate { "|l|c|p(8em)|l|l|p|p|p|" } + NC() bold("unicode") + NC() bold("visual") + NC() bold("unicodes") + NC() bold("tounicode") + NC() bold("index") + NC() bold("glyph") + NC() bold("adobe") + NC() bold("context") + NC() NR() for unicode, chr in fonts.iterators.characters(tfmdata) do local des, dat = descriptions[unicode], data[unicode] - local index = chr.index or 0 - local cname = (dat and dat.contextname) or "" - local aname = (dat and dat.adobename) or "" - local gname = (des and des.name) or "" - local mname = dat and dat.mathname + local index = chr.index or 0 + local tounicode = chr.tounicode + local isunicode = chr.unicode + local cname = (dat and dat.contextname) or "" + local aname = (dat and dat.adobename) or "" + local gname = (des and des.name) or "" + local mname = dat and dat.mathname if type(mname) ~= "string" then mname = "" end @@ -70,12 +83,52 @@ cname = mname end end - NC() tttf() context("U+%05X",unicode) - NC() char(unicode) - NC() tttf() context("%05X",index) - NC() if gname ~= "" then tttf() escaped(gname) end - NC() if aname ~= "" then tttf() context(aname) end - NC() if cname ~= "" then tttf() context(cname) end + NC() + tttf() + context("%05X",unicode) + NC() + char(unicode) + NC() + if isunicode then + tttf() + if type(isunicode) == "table" then + for i=1,#isunicode do + if i > 1 then + if i % 2 ~= 0 then + context.crlf() + else + context.space() + end + end + context("%05X",isunicode[i]) + end + else + context("%05X",isunicode) + end + end + NC() + if tounicode then + tttf() + context(tounicode) + end + NC() + tttf() + context("%05X",index) + NC() + if gname ~= "" then + tttf() + escaped(gname) + end + NC() + if aname ~= "" then + tttf() + context(aname) + end + NC() + if cname ~= "" then + tttf() + context(cname) + end NC() NR() end context.stoptabulate() @@ -100,14 +153,13 @@ \font\TestFont=#1 at #2 \setuplayout[style=\TestFont] \setupheadertexts[] - \setupfootertexts[#1 -- \pagenumber] - \setupfootertexts[pagenumber] + \setupfootertexts[#1\space\endash\space\pagenumber] \setuplayout[width=middle,height=middle,topspace=1cm,backspace=1cm] \TestFont \nonknuthmode \startcolumns[n=#3] - \TestFont - \ctxlua { moduledata.fonts.complete.all() } + \TestFont + \ctxlua { moduledata.fonts.complete.all() } \stopcolumns \page \endgroup} @@ -125,14 +177,16 @@ \TestFontB \setupinterlinespace[line=1.2\dimexpr#2\relax] \raggedcenter \nonknuthmode \startcolumns[n=#3] - \TestFontB - \ctxlua { moduledata.fonts.complete.glyphs() } + \TestFontB + \ctxlua { moduledata.fonts.complete.glyphs() } \stopcolumns \page \endgroup} \continueifinputfile{s-fonts-complete.mkiv} +\usemodule[art-01] \setuplayout[overview] \setupbodyfont[8pt] + \starttext % \ShowCompleteFont{name:dejavusansmono}{10pt}{1} @@ -140,7 +194,7 @@ % \ShowCompleteFont{name:officinasansbookitcregular}{10pt}{2} % \ShowCompleteFont{name:officinaserifbookitcregular}{10pt}{2} % \ShowCompleteFont{name:serpentineserifeflight}{10pt}{2} -\ShowCompleteFont{name:lmroman10-regular}{10pt}{1} +% \ShowCompleteFont{name:lmroman10-regular}{10pt}{1} % \ShowCompleteFont{name:lmtypewriter10-regular}{10pt}{2} % \ShowCompleteFont{lt55485}{10pt}{2} % \ShowCompleteFont{lmr10}{10pt}{2} @@ -157,4 +211,13 @@ % \ShowCompleteFont{name:palatinonovaregular}{11pt}{2} % \ShowCompleteFont{pirat.ttf}{12pt}{1} +\setuplayout[overview][footer=1cm] \setuplayout[overview]% \setupheadertexts[aegean.ttf] + +\ShowCompleteFont{file:aegean} {8pt}{1} +% \ShowCompleteFont{file:tsukurimashouminchops}{8pt}{1} +% \ShowCompleteFont{file:tsukurimashoumincho} {8pt}{1} +% \ShowCompleteFont{file:tsukurimashoukakups} {8pt}{1} +% \ShowCompleteFont{file:tsukurimashoukaku} {8pt}{1} +% \ShowCompleteFont{file:akkadian} {8pt}{1} + \stoptext diff --git a/tex/context/modules/mkiv/s-fonts-system.lua b/tex/context/modules/mkiv/s-fonts-system.lua index e05eef0fa..5d2692473 100644 --- a/tex/context/modules/mkiv/s-fonts-system.lua +++ b/tex/context/modules/mkiv/s-fonts-system.lua @@ -39,6 +39,8 @@ local sortedhash = table.sortedhash local formatters = string.formatters local concat = table.concat local lower = string.lower +local gsub = string.gsub +local find = string.find local function allfiles(specification) local pattern = lower(specification.pattern or "") @@ -202,3 +204,88 @@ function moduledata.fonts.system.showinstalledglyphnames(specification) end table.save("s-fonts-system-glyph-names.lua",names) end + +-- -- -- + +-- local skip = { +-- "adobeblank", +-- "veramo", +-- "unitedstates", +-- "tirek", +-- "svbasicmanual", +-- "sahel", +-- "prsprorg", +-- "piratdia", +-- "notoserifthai", +-- "coelacanthsubhdheavy", +-- } + +-- local function bad(name) +-- name = lower(name) +-- for i=1,#skip do +-- if find(name,skip[i]) then +-- return true +-- end +-- end +-- end + +-- function moduledata.fonts.system.showprivateglyphnames(specification) +-- specification = interfaces.checkedspecification(specification) +-- local paths = caches.getreadablepaths() +-- local files = { } +-- local names = table.setmetatableindex("table") +-- local f_u = formatters["%04X"] +-- for i=1,#paths do +-- local list = dir.glob(paths[i].."/fonts/o*/**.tmc") +-- for i=1,#list do +-- files[list[i]] = true +-- end +-- end +-- for filename in table.sortedhash(files) do +-- logs.report("system","fontfile: %s",file.nameonly(filename)) +-- local data = table.load(filename) +-- if data and data.format == "truetype" or data.format == "opentype" then +-- local basename = file.basename(data.resources.filename) +-- local cleanname = gsub(basename," ","") +-- if not bad(cleanname) then +-- local descriptions = data.descriptions +-- if descriptions then +-- local done = 0 +-- for u, d in sortedhash(descriptions) do +-- local dn = d.name +-- local du = d.unicode +-- if dn and du and (u >= 0xF0000 or (u >= 0xE000 and u <= 0xF8FF)) and not find(dn,"notdef") then +-- if type(du) == "table" then +-- local t = { } +-- for i=1,#du do +-- t[i] = f_u(du[i]) +-- end +-- du = concat(t," ") +-- end +-- if done == 0 then +-- logs.report("system","basename: %s",basename) +-- context.starttitle { title = basename } +-- context.start() +-- context.definefont( { "tempfont" }, { "file:" .. cleanname }) +-- context.starttabulate { "|T||T|T|" } +-- end +-- NC() context("%U",u) +-- NC() context.tempfont() context.char(u) -- could be getglyph +-- NC() ctx_verbatim(dn) +-- NC() context(du) +-- NC() NR() +-- done = done + 1 +-- end +-- end +-- if done > 0 then +-- logs.report("system","privates: %i",done) +-- context.stoptabulate() +-- context.stop() +-- context.stoptitle() +-- end +-- end +-- end +-- end +-- end +-- end + diff --git a/tex/context/modules/mkiv/s-fonts-system.mkiv b/tex/context/modules/mkiv/s-fonts-system.mkiv index 5613701d9..03599b0df 100644 --- a/tex/context/modules/mkiv/s-fonts-system.mkiv +++ b/tex/context/modules/mkiv/s-fonts-system.mkiv @@ -27,22 +27,24 @@ \installmodulecommandluasingle \showinstalledfonts {moduledata.fonts.system.showinstalled} \installmodulecommandluasingle \cacheinstalledfonts {moduledata.fonts.system.cacheinstalled} \installmodulecommandluasingle \showinstalledglyphnames {moduledata.fonts.system.showinstalledglyphnames} +%installmodulecommandluasingle \showprivateglyphnames {moduledata.fonts.system.showprivateglyphnames} \stopmodule \continueifinputfile{s-fonts-system.mkiv} -\usemodule[art-01] \setuplayout[overview] \setupbodyfont[7pt] +\usemodule[art-01] \setuplayout[overview] \setupbodyfont[6pt] \starttext % \showinstalledfonts -% \enabletrackers[otf.keepnames] + \enabletrackers[otf.keepnames] -% \cacheinstalledfonts[threshold=4000000,suffixes={otf,ttf,afm,pfb}] -% \cacheinstalledfonts[threshold=2000000,suffixes={otf,ttf,afm,pfb}] + \cacheinstalledfonts[suffixes={otf,ttf,afm}] +% \cacheinstalledfonts[threshold=4000000,suffixes={otf,ttf,afm}] +% \cacheinstalledfonts[threshold=2000000,suffixes={otf,ttf,afm}] - \showinstalledglyphnames +% \showinstalledglyphnames \stoptext diff --git a/tex/context/modules/mkiv/s-maps.mkiv b/tex/context/modules/mkiv/s-maps.mkiv index c7541babc..28e88af98 100644 --- a/tex/context/modules/mkiv/s-maps.mkiv +++ b/tex/context/modules/mkiv/s-maps.mkiv @@ -135,11 +135,11 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% 3 versions of layout with matching headers -\definepapersize +\definepapersize [maps] [width=21cm,height=26.5cm] -\setuppapersize +\setuppapersize [maps][maps] \setuplayout[ @@ -360,9 +360,9 @@ \xdef\MapsNumber{\the\numexpr (\the\year-1990)*2+1\relax}% \fi }% \doifnothing\MapsRunningAuthor - {\global\let\MapsRunningAuthor\MapsAuthor}% + {\glet\MapsRunningAuthor\MapsAuthor}% \doifnothing\MapsRunningTitle - {\global\let\MapsRunningTitle\MapsTitle}}% + {\glet\MapsRunningTitle\MapsTitle}}% \def\dostartArticle[#1]{% \MapsBibData[#1] diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 90f8f4f00..f97f82489 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 10/08/18 17:44:41 +-- merge date : 10/17/18 15:06:55 do -- begin closure to overcome local limits and interference @@ -9668,6 +9668,7 @@ function constructors.scale(tfmdata,specification) if isunicode then chr.unicode=isunicode chr.tounicode=tounicode(isunicode) + else end if hasquality then local ve=character.expansion_factor @@ -23846,35 +23847,41 @@ local function checkmathreplacements(tfmdata,fullname,fixitalics) for unicode,replacement in next,changed do local u=characters[unicode] local r=characters[replacement] - local n=u.next - local v=u.vert_variants - local h=u.horiz_variants - if fixitalics then - local ui=u.italic - if ui and not r.italic then + if u and r then + local n=u.next + local v=u.vert_variants + local h=u.horiz_variants + if fixitalics then + local ui=u.italic + if ui and not r.italic then + if trace_preparing then + report_prepare("using %i units of italic correction from %C for %U",ui,unicode,replacement) + end + r.italic=ui + end + end + if n and not r.next then if trace_preparing then - report_prepare("using %i units of italic correction from %C for %U",ui,unicode,replacement) + report_prepare("forcing %s for %C substituted by %U","incremental step",unicode,replacement) end - r.italic=ui + r.next=n end - end - if n and not r.next then - if trace_preparing then - report_prepare("forcing %s for %C substituted by %U","incremental step",unicode,replacement) + if v and not r.vert_variants then + if trace_preparing then + report_prepare("forcing %s for %C substituted by %U","vertical variants",unicode,replacement) + end + r.vert_variants=v end - r.next=n - end - if v and not r.vert_variants then - if trace_preparing then - report_prepare("forcing %s for %C substituted by %U","vertical variants",unicode,replacement) + if h and not r.horiz_variants then + if trace_preparing then + report_prepare("forcing %s for %C substituted by %U","horizontal variants",unicode,replacement) + end + r.horiz_variants=h end - r.vert_variants=v - end - if h and not r.horiz_variants then + else if trace_preparing then - report_prepare("forcing %s for %C substituted by %U","horizontal variants",unicode,replacement) + report_prepare("error replacing %C by %U",unicode,replacement) end - r.horiz_variants=h end end end @@ -31743,7 +31750,7 @@ if not modules then modules={} end modules ['font-otc']={ license="see context related readme files" } local insert,sortedkeys,sortedhash,tohash=table.insert,table.sortedkeys,table.sortedhash,table.tohash -local type,next=type,next +local type,next,tonumber=type,next,tonumber local lpegmatch=lpeg.match local utfbyte,utflen=utf.byte,utf.len local sortedhash=table.sortedhash @@ -31881,6 +31888,7 @@ local function addfeature(data,feature,specifications) if not specifications then return end + local p=lpeg.P("P")*(lpeg.patterns.hexdigit^1/function(s) return tonumber(s,16) end)*lpeg.P(-1) local function tounicode(code) if not code then return @@ -31898,10 +31906,17 @@ local function addfeature(data,feature,specifications) return u end end + local u=lpegmatch(p,code) + if u then + return u + end if not aglunicodes then aglunicodes=fonts.encodings.agl.unicodes end - return aglunicodes[code] + local u=aglunicodes[code] + if u then + return u + end end local coverup=otf.coverup local coveractions=coverup.actions |