From 15b67b20aa0d6c508578d0ca8cbdcd9cff9829a8 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Mon, 17 Dec 2018 18:19:48 +0100 Subject: 2018-12-17 16:49:00 --- tex/context/base/mkii/cont-new.mkii | 2 +- tex/context/base/mkii/context.mkii | 2 +- tex/context/base/mkii/mult-cs.mkii | 1 + tex/context/base/mkii/mult-de.mkii | 3 +- tex/context/base/mkii/mult-it.mkii | 3 +- tex/context/base/mkiv/back-pdf.mkiv | 8 +- tex/context/base/mkiv/char-ini.lua | 2 + tex/context/base/mkiv/cont-new.mkiv | 2 +- tex/context/base/mkiv/context.mkiv | 2 +- tex/context/base/mkiv/font-imp-dimensions.lua | 2 + tex/context/base/mkiv/font-imp-math.lua | 2 + tex/context/base/mkiv/font-imp-notused.lua | 2 + tex/context/base/mkiv/font-imp-properties.lua | 2 + tex/context/base/mkiv/font-imp-quality.lua | 2 + tex/context/base/mkiv/font-imp-reorder.lua | 2 + tex/context/base/mkiv/font-imp-tracing.lua | 110 ++ tex/context/base/mkiv/font-imp-unicode.lua | 2 + tex/context/base/mkiv/font-vfc.lua | 30 +- tex/context/base/mkiv/grph-img.lua | 746 -------------- tex/context/base/mkiv/grph-inc.lua | 315 +----- tex/context/base/mkiv/grph-inc.mkiv | 5 + tex/context/base/mkiv/l-lpeg.lua | 78 -- tex/context/base/mkiv/l-macro-imp-optimize.lua | 26 +- tex/context/base/mkiv/l-os.lua | 66 ++ tex/context/base/mkiv/l-unicode.lua | 209 ++-- tex/context/base/mkiv/lpdf-epd.lua | 2 +- tex/context/base/mkiv/lpdf-img.lua | 1052 -------------------- tex/context/base/mkiv/lpdf-ini.lua | 1 + tex/context/base/mkiv/lxml-tex.lua | 126 ++- tex/context/base/mkiv/pack-rul.mkiv | 8 + tex/context/base/mkiv/page-lin.mkvi | 4 + tex/context/base/mkiv/status-files.pdf | Bin 26052 -> 26042 bytes tex/context/base/mkiv/status-lua.pdf | Bin 269696 -> 268911 bytes tex/context/base/mkiv/trac-deb.lua | 2 + tex/context/base/mkiv/trac-log.lua | 2 +- tex/context/base/mkiv/typo-krn.lua | 3 - tex/context/interface/mkii/keys-cs.xml | 1 + tex/context/interface/mkii/keys-de.xml | 3 +- tex/context/interface/mkii/keys-it.xml | 3 +- tex/context/interface/mkiv/context-en.xml | 332 +++++- tex/context/interface/mkiv/i-backend.xml | 24 +- tex/context/interface/mkiv/i-block.xml | 7 + tex/context/interface/mkiv/i-buffer.xml | 2 +- tex/context/interface/mkiv/i-color.xml | 4 +- tex/context/interface/mkiv/i-columns.xml | 2 +- tex/context/interface/mkiv/i-common-argument.xml | 2 +- tex/context/interface/mkiv/i-common-value.xml | 35 + tex/context/interface/mkiv/i-context.pdf | Bin 857222 -> 864308 bytes tex/context/interface/mkiv/i-context.xml | 1 + tex/context/interface/mkiv/i-delimitedtext.xml | 5 +- tex/context/interface/mkiv/i-document.xml | 30 + tex/context/interface/mkiv/i-floats.xml | 27 + tex/context/interface/mkiv/i-fonts.xml | 4 +- tex/context/interface/mkiv/i-framed.xml | 20 +- tex/context/interface/mkiv/i-hspace.xml | 1 + tex/context/interface/mkiv/i-language.xml | 7 + tex/context/interface/mkiv/i-pagegrid.xml | 12 +- tex/context/interface/mkiv/i-readme.pdf | Bin 60779 -> 60780 bytes tex/context/interface/mkiv/i-ruby.xml | 1 + tex/context/interface/mkiv/i-startstop.xml | 2 +- tex/context/interface/mkiv/i-system.xml | 16 + tex/context/interface/mkiv/i-tagging.xml | 2 +- tex/context/interface/mkiv/i-token.xml | 31 + tex/context/interface/mkiv/i-unit.xml | 12 + tex/context/interface/mkiv/i-userdata.xml | 85 ++ tex/context/interface/mkiv/i-verbatim.xml | 4 +- tex/context/interface/mkiv/i-visualizer.xml | 14 +- tex/context/interface/mkiv/i-whitespace.xml | 4 +- tex/context/interface/mkiv/i-xtable.xml | 20 +- tex/context/modules/mkiv/s-fonts-shapes.lua | 2 +- tex/context/modules/mkiv/s-fonts-shapes.mkiv | 6 +- tex/context/modules/mkiv/s-fonts-variable.mkiv | 10 +- tex/generic/context/luatex/luatex-basics-gen.lua | 63 ++ tex/generic/context/luatex/luatex-fonts-merged.lua | 827 ++------------- tex/generic/context/luatex/luatex-fonts.lua | 1 - 75 files changed, 1281 insertions(+), 3165 deletions(-) delete mode 100644 tex/context/base/mkiv/grph-img.lua delete mode 100644 tex/context/base/mkiv/lpdf-img.lua create mode 100644 tex/context/interface/mkiv/i-userdata.xml (limited to 'tex') diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 4d04ebdb2..b5e91c7d6 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.12.07 19:37} +\newcontextversion{2018.12.17 16:39} %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 d5b74dd8d..547af354c 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.12.07 19:37} +\edef\contextversion{2018.12.17 16:39} %D For those who want to use this: diff --git a/tex/context/base/mkii/mult-cs.mkii b/tex/context/base/mkii/mult-cs.mkii index b2cbdb517..b10fb84fa 100644 --- a/tex/context/base/mkii/mult-cs.mkii +++ b/tex/context/base/mkii/mult-cs.mkii @@ -137,6 +137,7 @@ \setinterfacevariable{chemicals}{chemicals} \setinterfacevariable{chemistry}{chemistry} \setinterfacevariable{cite}{cite} +\setinterfacevariable{closed}{closed} \setinterfacevariable{color}{barevne} \setinterfacevariable{column}{column} \setinterfacevariable{columns}{sloupce} diff --git a/tex/context/base/mkii/mult-de.mkii b/tex/context/base/mkii/mult-de.mkii index 0958b3464..0a15a4f30 100644 --- a/tex/context/base/mkii/mult-de.mkii +++ b/tex/context/base/mkii/mult-de.mkii @@ -137,6 +137,7 @@ \setinterfacevariable{chemicals}{chemicals} \setinterfacevariable{chemistry}{chemistry} \setinterfacevariable{cite}{cite} +\setinterfacevariable{closed}{closed} \setinterfacevariable{color}{farbe} \setinterfacevariable{column}{column} \setinterfacevariable{columns}{spalten} @@ -418,7 +419,7 @@ \setinterfacevariable{positive}{positiv} \setinterfacevariable{postponing}{verschieben} \setinterfacevariable{postscript}{postscript} -\setinterfacevariable{precedingpage}{followingpage} +\setinterfacevariable{precedingpage}{precedingpage} \setinterfacevariable{preference}{einstellung} \setinterfacevariable{preview}{vorschau} \setinterfacevariable{previous}{vorig} diff --git a/tex/context/base/mkii/mult-it.mkii b/tex/context/base/mkii/mult-it.mkii index 7b32b022c..0b5ab2382 100644 --- a/tex/context/base/mkii/mult-it.mkii +++ b/tex/context/base/mkii/mult-it.mkii @@ -137,6 +137,7 @@ \setinterfacevariable{chemicals}{chemicals} \setinterfacevariable{chemistry}{chemistry} \setinterfacevariable{cite}{cite} +\setinterfacevariable{closed}{closed} \setinterfacevariable{color}{colore} \setinterfacevariable{column}{colonna} \setinterfacevariable{columns}{colonne} @@ -418,7 +419,7 @@ \setinterfacevariable{positive}{positivo} \setinterfacevariable{postponing}{posporre} \setinterfacevariable{postscript}{postscript} -\setinterfacevariable{precedingpage}{followingpage} +\setinterfacevariable{precedingpage}{precedingpage} \setinterfacevariable{preference}{preferenza} \setinterfacevariable{preview}{anteprima} \setinterfacevariable{previous}{precedente} diff --git a/tex/context/base/mkiv/back-pdf.mkiv b/tex/context/base/mkiv/back-pdf.mkiv index 6c663bf0f..a9a74cae4 100644 --- a/tex/context/base/mkiv/back-pdf.mkiv +++ b/tex/context/base/mkiv/back-pdf.mkiv @@ -33,7 +33,13 @@ \registerctxluafile{lpdf-tag}{} \registerctxluafile{lpdf-fmt}{} \registerctxluafile{lpdf-pde}{} -\registerctxluafile{lpdf-img}{optimize} + +\doifelsefileexists {lpdf-emb.lua} { + \registerctxluafile{lpdf-img}{optimize} +} { + % nothing +} + \registerctxluafile{lpdf-epa}{} \doifelsefileexists {lpdf-emb.lua} { diff --git a/tex/context/base/mkiv/char-ini.lua b/tex/context/base/mkiv/char-ini.lua index 1e8c1f7d3..62e509151 100644 --- a/tex/context/base/mkiv/char-ini.lua +++ b/tex/context/base/mkiv/char-ini.lua @@ -1287,6 +1287,8 @@ function characters.lower (str) return str and lpegmatch(utf8lower,str) or "" en function characters.upper (str) return str and lpegmatch(utf8upper,str) or "" end function characters.shaped(str) return str and lpegmatch(utf8shape,str) or "" end +lpeg.setutfcasers(characters.lower,characters.upper) + -- local str = [[ -- ÀÁÂÃÄÅàáâãäå àáâãäåàáâãäå ÀÁÂÃÄÅÀÁÂÃÄÅ AAAAAAaaaaaa -- ÆÇæç æçæç ÆÇÆÇ AECaec diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index a31442367..a6c862c7e 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.12.07 19:37} +\newcontextversion{2018.12.17 16:39} %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 0bc464b70..0b61408de 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.12.07 19:37} +\edef\contextversion{2018.12.17 16:39} \edef\contextkind {beta} %D For those who want to use this: diff --git a/tex/context/base/mkiv/font-imp-dimensions.lua b/tex/context/base/mkiv/font-imp-dimensions.lua index e658ef7bb..a7125625d 100644 --- a/tex/context/base/mkiv/font-imp-dimensions.lua +++ b/tex/context/base/mkiv/font-imp-dimensions.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['font-imp-dimensions'] = { license = "see context related readme files" } +if not context then return end + local next, type, tonumber = next, type, tonumber local fonts = fonts diff --git a/tex/context/base/mkiv/font-imp-math.lua b/tex/context/base/mkiv/font-imp-math.lua index 3a82c2a9e..d93ece405 100644 --- a/tex/context/base/mkiv/font-imp-math.lua +++ b/tex/context/base/mkiv/font-imp-math.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['font-imp-math'] = { license = "see context related readme files" } +if not context then return end + local next, type, tonumber = next, type, tonumber local fonts = fonts diff --git a/tex/context/base/mkiv/font-imp-notused.lua b/tex/context/base/mkiv/font-imp-notused.lua index 1c78db7aa..be36c9898 100644 --- a/tex/context/base/mkiv/font-imp-notused.lua +++ b/tex/context/base/mkiv/font-imp-notused.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['font-imp-notused'] = { license = "see context related readme files" } +if not context then return end + -- local next = next -- local utfbyte = utf.byte -- diff --git a/tex/context/base/mkiv/font-imp-properties.lua b/tex/context/base/mkiv/font-imp-properties.lua index 8cd22af69..5805235b7 100644 --- a/tex/context/base/mkiv/font-imp-properties.lua +++ b/tex/context/base/mkiv/font-imp-properties.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['font-imp-properties'] = { license = "see context related readme files" } +if not context then return end + local next, type, tonumber, select = next, type, tonumber, select local byte, find, formatters = string.byte, string.find, string.formatters local utfchar = utf.char diff --git a/tex/context/base/mkiv/font-imp-quality.lua b/tex/context/base/mkiv/font-imp-quality.lua index 930d036e1..224d8dc27 100644 --- a/tex/context/base/mkiv/font-imp-quality.lua +++ b/tex/context/base/mkiv/font-imp-quality.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['font-imp-quality'] = { license = "see context related readme files" } +if not context then return end + local next, type, tonumber = next, type, tonumber local byte = string.byte local insert = table.insert diff --git a/tex/context/base/mkiv/font-imp-reorder.lua b/tex/context/base/mkiv/font-imp-reorder.lua index 250aa47c6..b2dec781c 100644 --- a/tex/context/base/mkiv/font-imp-reorder.lua +++ b/tex/context/base/mkiv/font-imp-reorder.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['font-imp-reorder'] = { license = "see context related readme files" } +if not context then return end + local next = next local find = string.find local sortedhash, sortedkeys, sort = table.sortedhash, table.sortedkeys, table.sort diff --git a/tex/context/base/mkiv/font-imp-tracing.lua b/tex/context/base/mkiv/font-imp-tracing.lua index e6de494df..6ce445143 100644 --- a/tex/context/base/mkiv/font-imp-tracing.lua +++ b/tex/context/base/mkiv/font-imp-tracing.lua @@ -6,7 +6,10 @@ if not modules then modules = { } end modules ['font-imp-tracing'] = { license = "see context related readme files" } +if not context then return end + local next, type = next, type +local concat = table.concat local formatters = string.formatters local fonts = fonts @@ -19,6 +22,7 @@ local settings_to_array = utilities.parsers.settings_to_array local setmetatableindex = table.setmetatableindex local helpers = fonts.helpers +local appendcommandtable = helpers.appendcommandtable local prependcommands = helpers.prependcommands local charcommand = helpers.commands.char @@ -48,6 +52,8 @@ local r = 16384 * bp -- 65536 // 4 local f_1 = formatters["%.6F w 0 %.6F %.6F %.6F re f"] local f_2 = formatters["[] 0 d 0 J %.6F w %.6F %.6F %.6F %.6F re S"] +-- change this into w h d instead of h d w + local backcache = setmetatableindex(function(t,h) local h = h * bp local v = setmetatableindex(function(t,d) @@ -169,3 +175,107 @@ local specification = { registerotffeature(specification) registerafmfeature(specification) + +local f_m = formatters["%F %F m"] +local f_l = formatters["%F %F l"] +local f_b = formatters["[] 0 d 0 J %.6F w"] +local f_e = formatters["s"] + +local function ladder(list,docolor,nocolor,lst,offset,sign,default) + local l = lst[1] + local x1 = bp * (offset + l.kern) * sign + local y1 = bp * l.height + local t = { f_b(r,r/2), f_m(x1,y1) } + local n = 2 + local m = #lst + if default > 0 then + default = default * bp + r + else + default = default * bp - r + end + if m == 1 then + n = n + 1 t[n] = f_l(x1,default) + else + for i=1,m do + local l = lst[i] + local x2 = bp * (offset + l.kern) * sign + local y2 = bp * l.height + if i > 1 and y2 == 0 then + y2 = default + end + n = n + 1 t[n] = f_l(x2,y1) + n = n + 1 t[n] = f_l(x2,y2) + x1, y1 = x2, y2 + end + end + n = n + 1 t[n] = f_e() + list[#list+1] = docolor + list[#list+1] = { "pdf", "origin", concat(t," ") } + list[#list+1] = nocolor +end + +local function initialize(tfmdata,key,value) + if value then + if not backcolors then + local vfspecials = backends.pdf.tables.vfspecials + startcolor = vfspecials.startcolor + stopcolor = vfspecials.stopcolor + end + local characters = tfmdata.characters + local brcolor = startcolor("darkred") + local trcolor = startcolor("darkgreen") + local blcolor = startcolor("darkblue") + local tlcolor = startcolor("darkyellow") + local black = stopcolor + for unicode, character in next, characters do + local mathkern = character.mathkern + if mathkern then + -- more efficient would be co collect more in one pdf + -- directive but this is hardly used so not worth the + -- effort + local width = character.width or 0 + local height = character.height or 0 + local depth = character.depth or 0 + local list = { } + local br = mathkern.bottom_right + local tr = mathkern.top_right + local bl = mathkern.bottom_left + local tl = mathkern.top_left + if br then + ladder(list,brcolor,black,br,width,1,height) + end + if tr then + ladder(list,trcolor,black,tr,width,1,-depth) + end + if bl then + ladder(list,blcolor,black,bl,0,-1,height) + end + if tl then + ladder(list,tlcolor,black,tl,0,-1,-depth) + end + if #list > 0 then + local commands = character.commands + if commands then + character.commands = appendcommandtable(commands,list) + else + list[#list+1] = charcommand[unicode] + character.commands = list + end + end + end + end + end +end + +local specification = { + name = "staircase", + description = "show staircase kerns", + position=1, + manipulators = { + base = initialize, + node = initialize, + } +} + +registerotffeature(specification) +registerafmfeature(specification) diff --git a/tex/context/base/mkiv/font-imp-unicode.lua b/tex/context/base/mkiv/font-imp-unicode.lua index 9e1e3465e..ddb965ec9 100644 --- a/tex/context/base/mkiv/font-imp-unicode.lua +++ b/tex/context/base/mkiv/font-imp-unicode.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['font-imp-unicode'] = { license = "see context related readme files" } +if not context then return end + local next = next local fonts = fonts diff --git a/tex/context/base/mkiv/font-vfc.lua b/tex/context/base/mkiv/font-vfc.lua index 3e48422d6..dfe6b3afc 100644 --- a/tex/context/base/mkiv/font-vfc.lua +++ b/tex/context/base/mkiv/font-vfc.lua @@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['font-vfc'] = { license = "see context related readme files" } -local select = select +local select, type = select, type local insert = table.insert local fonts = fonts @@ -25,7 +25,7 @@ local dummy = { "comment" } function helpers.prependcommands(commands,...) insert(commands,1,push) for i=select("#",...),1,-1 do - local s = select(i,...) + local s = (select(i,...)) if s then insert(commands,1,s) end @@ -38,7 +38,31 @@ function helpers.appendcommands(commands,...) insert(commands,1,push) insert(commands,pop) for i=1,select("#",...) do - local s = select(i,...) + local s = (select(i,...)) + if s then + insert(commands,s) + end + end + return commands +end + +function helpers.prependcommandtable(commands,t) + insert(commands,1,push) + for i=#t,1,-1 do + local s = t[i] + if s then + insert(commands,1,s) + end + end + insert(commands,pop) + return commands +end + +function helpers.appendcommandtable(commands,t) + insert(commands,1,push) + insert(commands,pop) + for i=1,#t do + local s = t[i] if s then insert(commands,s) end diff --git a/tex/context/base/mkiv/grph-img.lua b/tex/context/base/mkiv/grph-img.lua deleted file mode 100644 index c76733cbf..000000000 --- a/tex/context/base/mkiv/grph-img.lua +++ /dev/null @@ -1,746 +0,0 @@ -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 - 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 334a0b536..ee4ed2a28 100644 --- a/tex/context/base/mkiv/grph-inc.lua +++ b/tex/context/base/mkiv/grph-inc.lua @@ -54,8 +54,7 @@ local concat, insert, remove = table.concat, table.insert, table.remove local todimen = string.todimen local collapsepath = file.collapsepath local formatters = string.formatters -local formatcolumns = utilities.formatters.formatcolumns -local max, odd = math.max, math.odd +local odd = math.odd local P, R, S, Cc, C, Cs, Ct, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.Cc, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.match @@ -2164,315 +2163,3 @@ implement { end end } - --- This is an experiment. The following method uses Lua to handle the embedding --- using the epdf library. This feature will be used when we make the transition --- from the pre 1.10 epdf library (using an unsuported low level poppler api) to a --- new (lightweight, small and statically compiled) library. More on that later. --- --- The method implemented below has the same performance as the hard coded inclusion --- but opens up some possibilities (like merging fonts) that I will look into some --- day. - -local function pdf_checker(data) - local request = data.request - local used = data.used - if request and used and not request.scanimage then - local image = lpdf.epdf.image - local openpdf = image.open - local closepdf = image.close - local querypdf = image.query - local copypage = image.copy - local pdfdoc = nil - request.scanimage = function(t) - pdfdoc = openpdf(t.filename,request.userpassword,request.ownerpassword) - if pdfdoc then - -- - pdfdoc.nofcopiedpages = 0 - -- - local info = querypdf(pdfdoc,request.page) - if info then - local bbox = info and info.boundingbox or { 0, 0, 0, 0 } - local height = bbox[4] - bbox[2] - local width = bbox[3] - bbox[1] - local rotation = info.rotation or 0 - if rotation == 90 then - rotation, height, width = 3, width, height - elseif rotation == 180 then - rotation = 2 - elseif rotation == 270 then - rotation, height, width = 1, width, height - elseif rotation == 1 or rotation == 3 then - height, width = width, height - else - rotation = 0 - end - return { - filename = filename, - -- page = 1, - pages = pdfdoc.nofpages, - width = width, - height = height, - depth = 0, - colordepth = 0, - xres = 0, - yres = 0, - xsize = width, - ysize = height, - rotation = rotation, - pdfdoc = pdfdoc, - } - end - end - end - request.copyimage = function(t) - if not pdfdoc then - pdfdoc = t.pdfdoc - end - if pdfdoc then - local result = copypage(pdfdoc,request.page,nil,request.compact,request.width,request.height,request.attr) - pdfdoc.nofcopiedpages = pdfdoc.nofcopiedpages + 1 - if pdfdoc.nofcopiedpages >= pdfdoc.nofpages then - closepdf(pdfdoc) - pdfdoc = nil - t.pdfdoc = nil - end - return result - else - -- message, should not happen as we always first scan so that reopens - end - end - end - 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) - if result then - local xsize = result.xsize or 0 - local ysize = result.ysize or 0 - local xres = result.xres or 0 - local yres = result.yres or 0 - if xres == 0 or yres == 0 then - xres = 300 - yres = 300 - end - result.xsize = xsize - result.ysize = ysize - result.xres = xres - result.yres = yres - result.width = result.width or ((72/xres) * xsize / bpfactor) - result.height = result.height or ((72/yres) * ysize / bpfactor) - result.depth = result.depth or 0 - result.filename = filename - result.colordepth = result.colordepth or 0 - result.rotation = result.rotation or 0 - result.colorspace = result.colorspace or 0 - return result - else - return { error = "fatal error" } - end -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 result = wrappedidentify(identify,t.filename) - found = not result.error - return { - filename = result.filename, - width = result.width, - height = result.height, - depth = result.depth, - colordepth = result.colordepth, - xres = result.xres, - yres = result.yres, - xsize = result.xsize, - ysize = result.ysize, - rotation = result.rotation, - colorspace = result.colorspace, - } - 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 result = wrappedidentify(identify,t.filename) - found = not result.error - return { - filename = result.filename, - width = result.width, - height = result.height, - depth = result.depth, - colordepth = result.colordepth, - xres = result.xres, - yres = result.yres, - xsize = result.xsize, - ysize = result.ysize, - rotation = result.rotation, - colorspace = result.colorspace, - } - 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 result = wrappedidentify(identify,t.filename) - found = not result.error - return { - filename = result.filename, - width = result.width, - height = result.height, - depth = result.depth, - colordepth = result.colordepth, - xres = result.xres, - yres = result.yres, - xsize = result.xsize, - ysize = result.ysize, - rotation = result.rotation, - colorspace = result.colorspace, - 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) - checkers.pdf = v and pdf_checker or nil - report("%s Lua based PDF inclusion",v and "enabling" or "disabling") -end) - -directives.register("graphics.jpg.uselua",function(v) - checkers.jpg = v and jpg_checker or nil - report("%s Lua based JPG inclusion",v and "enabling" or "disabling") -end) - -directives.register("graphics.jp2.uselua",function(v) - checkers.jp2 = v and jp2_checker or nil - report("%s Lua based JP2 inclusion",v and "enabling" or "disabling") -end) - -directives.register("graphics.png.uselua",function(v) - checkers.png = v and png_checker or nil - report("%s Lua based PNG inclusion",v and "enabling" or "disabling") -end) - -directives.register("graphics.uselua",function(v) - checkers.pdf = v and pdf_checker or nil - checkers.jpg = v and jpg_checker or nil - checkers.jp2 = v and jp2_checker or nil - checkers.png = v and png_checker or nil - -- report("%s Lua based PDF, PNG, JPG and JP2 inclusion",v and "enabling" or "disabling") -end) - --- directives.enable("graphics.pdf.uselua") --- --- local filename = "luatex.pdf" --- --- for i=1,240 do --- context(function() --- context.startTEXpage() --- context.externalfigure( { filename }, { page = i } ) --- 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) - return wrapimage(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 width or height then - context.scale ( - { - width = width, - height = height, - }, - flush(bitmap) - ) - else - context(flush(bitmap)) - end -end - - diff --git a/tex/context/base/mkiv/grph-inc.mkiv b/tex/context/base/mkiv/grph-inc.mkiv index 4668b6f48..87ea14ae9 100644 --- a/tex/context/base/mkiv/grph-inc.mkiv +++ b/tex/context/base/mkiv/grph-inc.mkiv @@ -22,6 +22,11 @@ \registerctxluafile{grph-img}{} \registerctxluafile{grph-inc}{} + +\doifelsefileexists {grph-chk.lua} { + \registerctxluafile{grph-chk}{} +} {} + \registerctxluafile{grph-con}{} \registerctxluafile{grph-fil}{} \registerctxluafile{grph-mem}{} diff --git a/tex/context/base/mkiv/l-lpeg.lua b/tex/context/base/mkiv/l-lpeg.lua index eb55a55a0..51bc1d3df 100644 --- a/tex/context/base/mkiv/l-lpeg.lua +++ b/tex/context/base/mkiv/l-lpeg.lua @@ -657,83 +657,6 @@ function lpeg.counter(pattern,action) end end --- utf extensies - --- utf = utf or (unicode and unicode.utf8) or { } -utf = utf or { } - -local utfcharacters = utf and utf.characters or string.utfcharacters -local utfgmatch = utf and utf.gmatch -local utfchar = utf and utf.char - -lpeg.UP = lpeg.P - -if utfcharacters then - - function lpeg.US(str) - local p = P(false) - for uc in utfcharacters(str) do - p = p + P(uc) - end - return p - end - - -elseif utfgmatch then - - function lpeg.US(str) - local p = P(false) - for uc in utfgmatch(str,".") do - p = p + P(uc) - end - return p - end - -else - - function lpeg.US(str) - local p = P(false) - local f = function(uc) - p = p + P(uc) - end - lpegmatch((utf8char/f)^0,str) - return p - end - -end - -local range = utf8byte * utf8byte + Cc(false) -- utf8byte is already a capture - -function lpeg.UR(str,more) - local first, last - if type(str) == "number" then - first = str - last = more or first - else - first, last = lpegmatch(range,str) - if not last then - return P(str) - end - end - if first == last then - return P(str) - elseif utfchar and (last - first < 8) then -- a somewhat arbitrary criterium - local p = P(false) - for i=first,last do - p = p + P(utfchar(i)) - end - return p -- nil when invalid range - else - local f = function(b) - return b >= first and b <= last - end - -- tricky, these nested captures - return utf8byte / f -- nil when invalid range - end -end - --- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω")) - -- lpeg.print(lpeg.R("ab","cd","gh")) -- lpeg.print(lpeg.P("a","b","c")) -- lpeg.print(lpeg.S("a","b","c")) @@ -1052,7 +975,6 @@ function lpeg.utfreplacer(list,insensitive) end end - -- local t = { "start", "stoep", "staart", "paard" } -- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1) diff --git a/tex/context/base/mkiv/l-macro-imp-optimize.lua b/tex/context/base/mkiv/l-macro-imp-optimize.lua index 982548785..7d7fafefd 100644 --- a/tex/context/base/mkiv/l-macro-imp-optimize.lua +++ b/tex/context/base/mkiv/l-macro-imp-optimize.lua @@ -47,17 +47,21 @@ if LUAVERSION >= 5.3 and lua.macros then -- ]] lua.macros.resolvestring [[ -#define band(a,b) (a&b) -#define bnot(a) (~a&0xFFFFFFFF) -#define bor(a,b) ((a|b)&0xFFFFFFFF) -#define btest(a,b) ((a&b)~=0) -#define bxor(a,b) ((a~b)&0xFFFFFFFF) -#define rshift(a,b) ((a&b)~=0) -#define extract(a,b,c) ((a>>b)&~(-1<>b)&0x1) -#define lshift(a,b) ((a<>b)&0xFFFFFFFF) -#define intdiv(a,b) (a//b) +#define band(a,b) ((a)&(b)) +#define bnot(a) (~(a)&0xFFFFFFFF) +#define bor(a,b) (((a)|(b))&0xFFFFFFFF) +#define btest(a,b) (((a)&(b))~=0) +#define bxor(a,b) (((a)~(b))&0xFFFFFFFF) +#define rshift(a,b) (((a)&(b))~=0) +#define extract(a,b,c) (((a)>>(b))&~(-1<<(c))) +#define extract(a,b) (((a)>>(b))&0x1) +#define extract1(a,b) ((a >> b) & 0x01) +#define extract2(a,b) ((a >> b) & 0x03) +#define extract4(a,b) ((a >> b) & 0x0F) +#define lshift(a,b) (((a)<<(b))&0xFFFFFFFF) +#define rshift(a,b) (((a)>>(b))&0xFFFFFFFF) +#define intdiv(a,b) ((a)//(b)) +#define idiv(a,b) ((a)//(b)) ]] end diff --git a/tex/context/base/mkiv/l-os.lua b/tex/context/base/mkiv/l-os.lua index c2a903f5c..cf469f79d 100644 --- a/tex/context/base/mkiv/l-os.lua +++ b/tex/context/base/mkiv/l-os.lua @@ -32,6 +32,72 @@ local concat = table.concat local random, ceil, randomseed = math.random, math.ceil, math.randomseed local rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring = rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring +-- This check needs to happen real early on. Todo: we can pick it up from the commandline +-- if we pass --binpath= (which is useful anyway) + +do + local selfdir = os.selfdir + if selfdir == "" then + selfdir = nil + end + if not selfdir then + -- We need a fallback plan so let's see what we get. + if arg then + -- passed by mtx-context ... saves network access + for i=1,#arg do + local a = arg[i] + if find(a,"^%-%-[c:]*texmfbinpath=") then + selfdir = gsub(a,"^.-=","") + break + end + end + end + if not selfdir then + selfdir = os.selfbin or "luatex" + if find(selfdir,"[/\\]") then + selfdir = gsub(selfdir,"[/\\][^/\\]*$","") + elseif os.getenv then + local path = os.getenv("PATH") + local name = gsub(selfdir,"^.*[/\\][^/\\]","") + local patt = "[^:]+" + if os.type == "windows" then + patt = "[^;]+" + name = name .. ".exe" + end + local isfile + if lfs then + -- we're okay as lfs is assumed present + local attributes = lfs.attributes + isfile = function(name) + local a = attributes(name,"mode") + return a == "file" or a == "link" or nil + end + else + -- we're not okay and much will not work as we miss lfs + local open = io.open + isfile = function(name) + local f = open(name) + if f then + f:close() + return true + end + end + end + for p in gmatch(path,patt) do + -- possible speedup: there must be tex in 'p' + if isfile(p .. "/" .. name) then + selfdir = p + break + end + end + end + end + -- let's hope we're okay now + os.selfdir = selfdir or "." + end +end +-- print(os.selfdir) os.exit() + -- The following code permits traversing the environment table, at least in luatex. Internally all -- environment names are uppercase. diff --git a/tex/context/base/mkiv/l-unicode.lua b/tex/context/base/mkiv/l-unicode.lua index 433736602..13e0a3fa1 100644 --- a/tex/context/base/mkiv/l-unicode.lua +++ b/tex/context/base/mkiv/l-unicode.lua @@ -21,8 +21,8 @@ if not modules then modules = { } end modules ['l-unicode'] = { -- todo: utf.sub replacement (used in syst-aux) -- we put these in the utf namespace: --- used : byte char gmatch len lower sub upper --- not used : dump find format gfind gsub match rep reverse +-- used : byte char len lower sub upper +-- not used : dump find format gmatch gfind gsub match rep reverse -- utf = utf or (unicode and unicode.utf8) or { } @@ -33,8 +33,21 @@ if not modules then modules = { } end modules ['l-unicode'] = { utf = utf or { } unicode = nil -utf.characters = utf.characters or string.utfcharacters -utf.values = utf.values or string.utfvalues +if not string.utfcharacters then + + -- New: this gmatch hack is taken from the Lua 5.2 book. It's about two times slower + -- than the built-in string.utfcharacters. + + local gmatch = string.gmatch + + function string.characters(str) + return gmatch(str,".[\128-\191]*") + end + + +end + +utf.characters = string.utfcharacters -- string.utfvalues -- string.utfcharacters @@ -60,13 +73,11 @@ local bytepairs = string.bytepairs local finder = lpeg.finder local replacer = lpeg.replacer -local utfvalues = utf.values -local utfgmatch = utf.gmatch -- not always present - local p_utftype = patterns.utftype local p_utfstricttype = patterns.utfstricttype local p_utfoffset = patterns.utfoffset -local p_utf8char = patterns.utf8character +local p_utf8character = patterns.utf8character +local p_utf8char = patterns.utf8char local p_utf8byte = patterns.utf8byte local p_utfbom = patterns.utfbom local p_newline = patterns.newline @@ -169,10 +180,8 @@ if not utf.byte then if not utf.byte then - local utf8byte = patterns.utf8byte - function utf.byte(c) - return lpegmatch(utf8byte,c) + return lpegmatch(p_utf8byte,c) end end @@ -286,7 +295,7 @@ if not utf.len then -- -- alternative 1: 0.77 -- - -- local utfcharcounter = utfbom^-1 * Cs((p_utf8char/'!')^0) + -- local utfcharcounter = utfbom^-1 * Cs((p_utf8character/'!')^0) -- -- function utf.len(str) -- return #lpegmatch(utfcharcounter,str or "") @@ -296,7 +305,7 @@ if not utf.len then -- -- local n = 0 -- - -- local utfcharcounter = utfbom^-1 * (p_utf8char/function() n = n + 1 end)^0 -- slow + -- local utfcharcounter = utfbom^-1 * (p_utf8character/function() n = n + 1 end)^0 -- slow -- -- function utf.length(str) -- n = 0 @@ -373,7 +382,7 @@ if not utf.sub then -- inefficient as lpeg just copies ^n -- local function sub(str,start,stop) - -- local pattern = p_utf8char^-(start-1) * C(p_utf8char^-(stop-start+1)) + -- local pattern = p_utf8character^-(start-1) * C(p_utf8character^-(stop-start+1)) -- inspect(pattern) -- return lpegmatch(pattern,str) or "" -- end @@ -396,7 +405,7 @@ if not utf.sub then -- end -- end -- - -- local pattern = Cmt(p_utf8char,slide)^0 + -- local pattern = Cmt(p_utf8character,slide)^0 -- -- function utf.sub(str,start,stop) -- todo: from the end -- if not start then @@ -451,11 +460,11 @@ if not utf.sub then end end - local pattern_zero = Cmt(p_utf8char,slide_zero)^0 - local pattern_one = Cmt(p_utf8char,slide_one )^0 - local pattern_two = Cmt(p_utf8char,slide_two )^0 + local pattern_zero = Cmt(p_utf8character,slide_zero)^0 + local pattern_one = Cmt(p_utf8character,slide_one )^0 + local pattern_two = Cmt(p_utf8character,slide_two )^0 - local pattern_first = C(patterns.utf8character) + local pattern_first = C(p_utf8character) function utf.sub(str,start,stop) if not start then @@ -551,7 +560,7 @@ end -- a replacement for simple gsubs: -- function utf.remapper(mapping) --- local pattern = Cs((p_utf8char/mapping)^0) +-- local pattern = Cs((p_utf8character/mapping)^0) -- return function(str) -- if not str or str == "" then -- return "" @@ -573,16 +582,16 @@ function utf.remapper(mapping,option,action) -- static also returns a pattern return "" else if not pattern then - pattern = Cs((tabletopattern(mapping)/action + p_utf8char)^0) + pattern = Cs((tabletopattern(mapping)/action + p_utf8character)^0) end return lpegmatch(pattern,str) end end elseif option == "pattern" then - return Cs((tabletopattern(mapping)/action + p_utf8char)^0) + return Cs((tabletopattern(mapping)/action + p_utf8character)^0) -- elseif option == "static" then else - local pattern = Cs((tabletopattern(mapping)/action + p_utf8char)^0) + local pattern = Cs((tabletopattern(mapping)/action + p_utf8character)^0) return function(str) if not str or str == "" then return "" @@ -593,9 +602,9 @@ function utf.remapper(mapping,option,action) -- static also returns a pattern end elseif variant == "function" then if option == "pattern" then - return Cs((p_utf8char/mapping + p_utf8char)^0) + return Cs((p_utf8character/mapping + p_utf8character)^0) else - local pattern = Cs((p_utf8char/mapping + p_utf8char)^0) + local pattern = Cs((p_utf8character/mapping + p_utf8character)^0) return function(str) if not str or str == "" then return "" @@ -642,9 +651,9 @@ end -- inspect(utf.split("a b c d",true)) local utflinesplitter = p_utfbom^-1 * lpeg.tsplitat(p_newline) -local utfcharsplitter_ows = p_utfbom^-1 * Ct(C(p_utf8char)^0) -local utfcharsplitter_iws = p_utfbom^-1 * Ct((p_whitespace^1 + C(p_utf8char))^0) -local utfcharsplitter_raw = Ct(C(p_utf8char)^0) +local utfcharsplitter_ows = p_utfbom^-1 * Ct(C(p_utf8character)^0) +local utfcharsplitter_iws = p_utfbom^-1 * Ct((p_whitespace^1 + C(p_utf8character))^0) +local utfcharsplitter_raw = Ct(C(p_utf8character)^0) patterns.utflinesplitter = utflinesplitter @@ -780,7 +789,7 @@ local utf_32_le_linesplitter = utf_32_le_getbom * lpeg.tsplitat(patterns.utf_32_ -- if right then -- local now = 256*left + right -- if more > 0 then --- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong +-- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- more = 0 -- r = r + 1 -- result[r] = utfchar(now) @@ -809,7 +818,7 @@ local utf_32_le_linesplitter = utf_32_le_getbom * lpeg.tsplitat(patterns.utf_32_ -- if right then -- local now = 256*right + left -- if more > 0 then --- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong +-- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- more = 0 -- r = r + 1 -- result[r] = utfchar(now) @@ -839,7 +848,7 @@ local utf_32_le_linesplitter = utf_32_le_getbom * lpeg.tsplitat(patterns.utf_32_ -- if right then -- local now = 256*right + left -- if more > 0 then --- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong +-- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- more = 0 -- r = r + 1 -- result[r] = utfchar(now) @@ -916,7 +925,7 @@ local more = 0 local p_utf16_to_utf8_be = C(1) * C(1) /function(left,right) local now = 256*byte(left) + byte(right) if more > 0 then - now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong + now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 more = 0 return utfchar(now) elseif now >= 0xD800 and now <= 0xDBFF then @@ -930,7 +939,7 @@ end local p_utf16_to_utf8_le = C(1) * C(1) /function(right,left) local now = 256*byte(left) + byte(right) if more > 0 then - now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong + now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 more = 0 return utfchar(now) elseif now >= 0xD800 and now <= 0xDBFF then @@ -1124,15 +1133,6 @@ function utf.utf8_to_utf16(str,littleendian,nobom) end end --- function utf.tocodes(str,separator) -- can be sped up with an lpeg --- local t, n = { }, 0 --- for u in utfvalues(str) do --- n = n + 1 --- t[n] = format("0x%04X",u) --- end --- return concat(t,separator or " ") --- end - local pattern = Cs ( (p_utf8byte / function(unicode ) return format( "0x%04X", unicode) end) * (p_utf8byte * Carg(1) / function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0 @@ -1168,25 +1168,10 @@ end -- -local p_nany = p_utf8char / "" +do -if utfgmatch then - - function utf.count(str,what) - if type(what) == "string" then - local n = 0 - for _ in utfgmatch(str,what) do - n = n + 1 - end - return n - else -- 4 times slower but still faster than / function - return #lpegmatch(Cs((P(what)/" " + p_nany)^0),str) - end - end - -else - - local cache = { } + local p_nany = p_utf8character / "" + local cache = { } function utf.count(str,what) if type(what) == "string" then @@ -1203,23 +1188,7 @@ else end --- maybe also register as string.utf* - - -if not utf.characters then - - -- New: this gmatch hack is taken from the Lua 5.2 book. It's about two times slower - -- than the built-in string.utfcharacters. - - function utf.characters(str) - return gmatch(str,".[\128-\191]*") - end - - string.utfcharacters = utf.characters - -end - -if not utf.values then +if not string.utfvalues then -- So, a logical next step is to check for the values variant. It over five times -- slower than the built-in string.utfvalues. I optimized it a bit for n=0,1. @@ -1231,7 +1200,7 @@ if not utf.values then -- we share this one end - -- function utf.values(str) + -- function string.utfvalues(str) -- local n = #str -- if n == 0 then -- return wrap(dummy) @@ -1246,7 +1215,7 @@ if not utf.values then -- -- faster: - function utf.values(str) + function string.utfvalues(str) local n = #str if n == 0 then return dummy @@ -1269,11 +1238,11 @@ if not utf.values then -- slower: -- - -- local pattern = C(patterns.utf8character) * Cp() - -- ----- pattern = patterns.utf8character/utfbyte * Cp() - -- ----- pattern = patterns.utf8byte * Cp() + -- local pattern = C(p_utf8character) * Cp() + -- ----- pattern = p_utf8character/utfbyte * Cp() + -- ----- pattern = p_utf8byte * Cp() -- - -- function utf.values(str) -- one of the cases where a find is faster than an lpeg + -- function string.utfvalues(str) -- one of the cases where a find is faster than an lpeg -- local n = #str -- if n == 0 then -- return dummy @@ -1292,10 +1261,10 @@ if not utf.values then -- end -- end - string.utfvalues = utf.values - end +utf.values = string.utfvalues + function utf.chrlen(u) -- u is number return (u < 0x80 and 1) or @@ -1364,3 +1333,73 @@ function string.utfpadd(s,n) end return s end + +-- goodies + +do + + local utfcharacters = utf.characters or string.utfcharacters + local utfchar = utf.char or string.utfcharacter + + lpeg.UP = P + + if utfcharacters then + + function lpeg.US(str) + local p = P(false) + for uc in utfcharacters(str) do + p = p + P(uc) + end + return p + end + + else + + function lpeg.US(str) + local p = P(false) + local f = function(uc) + p = p + P(uc) + end + lpegmatch((p_utf8char/f)^0,str) + return p + end + + end + + local range = p_utf8byte * p_utf8byte + Cc(false) -- utf8byte is already a capture + + function lpeg.UR(str,more) + local first, last + if type(str) == "number" then + first = str + last = more or first + else + first, last = lpegmatch(range,str) + if not last then + return P(str) + end + end + if first == last then + return P(str) + end + if not utfchar then + utfchar = utf.char -- maybe delayed + end + if utfchar and (last - first < 8) then -- a somewhat arbitrary criterium + local p = P(false) + for i=first,last do + p = p + P(utfchar(i)) + end + return p -- nil when invalid range + else + local f = function(b) + return b >= first and b <= last + end + -- tricky, these nested captures + return p_utf8byte / f -- nil when invalid range + end + end + + -- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω")) + +end diff --git a/tex/context/base/mkiv/lpdf-epd.lua b/tex/context/base/mkiv/lpdf-epd.lua index a5eab016f..fe94a430b 100644 --- a/tex/context/base/mkiv/lpdf-epd.lua +++ b/tex/context/base/mkiv/lpdf-epd.lua @@ -1280,7 +1280,7 @@ if img then do -- image attributes FormType = 1, BBox = pageinfo.cropbox, - -- MetaData = copy(xref,copied,root,"MetaData"), + -- Metadata = copy(xref,copied,root,"Metadata"), -- Group = copy(xref,copied,page,"Group"), -- LastModified = copy(xref,copied,page,"LastModified"), -- Metadata = copy(xref,copied,page,"Metadata"), diff --git a/tex/context/base/mkiv/lpdf-img.lua b/tex/context/base/mkiv/lpdf-img.lua deleted file mode 100644 index ba4d4ff8e..000000000 --- a/tex/context/base/mkiv/lpdf-img.lua +++ /dev/null @@ -1,1052 +0,0 @@ -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 createimage = images.create - -local trace = false - -local report_jpg = logs.reporter("graphics","jpg") -local report_jp2 = logs.reporter("graphics","jp2") -local report_png = logs.reporter("graphics","png") - -trackers.register("graphics.backend", function(v) trace = v end) - -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 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 - } + specification.attr - if trace then - report_jpg("%s: width %i, height %i, colordepth %i, size %i",filename,xsize,ysize,colordepth,#content) - end - return createimage { - 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 - -- 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 - } + specification.attr - if trace then - report_jp2("%s: width %i, height %i, size %i",filename,xsize,ysize,#content) - end - return createimage { - 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") -- todo: in-mem too - 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, - } + specification.attr - 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 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 createimage { - 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 createimage { - 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/lpdf-ini.lua b/tex/context/base/mkiv/lpdf-ini.lua index 769b54b6c..09a4678a1 100644 --- a/tex/context/base/mkiv/lpdf-ini.lua +++ b/tex/context/base/mkiv/lpdf-ini.lua @@ -1208,6 +1208,7 @@ do function lpdf.getcatalog() if checkcatalog() then + catalog.Type = pdfconstant("Catalog") return pdfreference(pdfimmediateobject(tostring(catalog))) end end diff --git a/tex/context/base/mkiv/lxml-tex.lua b/tex/context/base/mkiv/lxml-tex.lua index 8bd5429cf..ae3edba56 100644 --- a/tex/context/base/mkiv/lxml-tex.lua +++ b/tex/context/base/mkiv/lxml-tex.lua @@ -2460,52 +2460,56 @@ end -- parameters -local function setatt(id,name,value) - local e = getid(id) - if e then - local a = e.at - if a then - a[name] = value - else - e.at = { [name] = value } +do + + local function setatt(id,name,value) + local e = getid(id) + if e then + local a = e.at + if a then + a[name] = value + else + e.at = { [name] = value } + end end end -end -local function setpar(id,name,value) - local e = getid(id) - if e then - local p = e.pa - if p then - p[name] = value - else - e.pa = { [name] = value } + local function setpar(id,name,value) + local e = getid(id) + if e then + local p = e.pa + if p then + p[name] = value + else + e.pa = { [name] = value } + end end end -end -lxml.setatt = setatt -lxml.setpar = setpar + lxml.setatt = setatt + lxml.setpar = setpar -function lxml.setattribute(id,pattern,name,value) - local collected = xmlapplylpath(getid(id),pattern) - if collected then - for i=1,#collected do - setatt(collected[i],name,value) + function lxml.setattribute(id,pattern,name,value) + local collected = xmlapplylpath(getid(id),pattern) + if collected then + for i=1,#collected do + setatt(collected[i],name,value) + end end end -end -function lxml.setparameter(id,pattern,name,value) - local collected = xmlapplylpath(getid(id),pattern) - if collected then - for i=1,#collected do - setpar(collected[i],name,value) + function lxml.setparameter(id,pattern,name,value) + local collected = xmlapplylpath(getid(id),pattern) + if collected then + for i=1,#collected do + setpar(collected[i],name,value) + end end end -end -lxml.setparam = lxml.setparameter + lxml.setparam = lxml.setparameter + +end -- relatively new: @@ -2735,3 +2739,59 @@ function texfinalizers.xml(collected,name,setup) buffers.assign(name,strip(xmltostring(root))) context.xmlprocessbuffer(name,name,setup or (name..":setup")) end + +-- experiment + +do + + local xmltoelement = xml.toelement + local xmlreindex = xml.reindex + + function lxml.replace(root,pattern,whatever) + if type(root) == "string" then + root = lxml.getid(root) + end + local collected = xmlapplylpath(root,pattern) + if collected then + local isstring = type(whatever) == "string" + for c=1,#collected do + local e = collected[c] + local p = e.__p__ + if p then + local d = p.dt + local n = e.ni + local w = isstring and whatever or whatever(e) + if w then + local t = xmltoelement(w,root).dt + if t then + t.__p__ = p + if type(t) == "table" then + local t1 = t[1] + d[n] = t1 + t1.at.type = e.at.type or t1.at.type + for i=2,#t do + n = n + 1 + insert(d,n,t[i]) + end + else + d[n] = t + end + xmlreindex(d) -- probably not needed + end + end + end + end + end + end + + -- function document.mess_around(root) + -- lxml.replace( + -- root, + -- "p[@variant='foo']", + -- function(c) + -- return (string.gsub(tostring(c),"foo","%1")) + -- end + -- ) + -- end + +end diff --git a/tex/context/base/mkiv/pack-rul.mkiv b/tex/context/base/mkiv/pack-rul.mkiv index f3ac8f6e8..3cbb731fe 100644 --- a/tex/context/base/mkiv/pack-rul.mkiv +++ b/tex/context/base/mkiv/pack-rul.mkiv @@ -141,6 +141,7 @@ \setupframed [\c!width=\v!fit, \c!height=\v!broad, + %\c!minheight=\zeropoint, %\c!lines=, \c!offset=.25\exheight, % \defaultframeoffset \c!empty=\v!no, @@ -1637,6 +1638,13 @@ \fi \ifconditional\c_framed_has_height \ht\b_framed_normal\d_framed_height + \else + \edef\p_framed_minheight{\framedparameter\c!minheight}% + \ifx\p_framed_minheight\empty \else + \ifdim\ht\b_framed_normal<\p_framed_minheight + \ht\b_framed_normal\p_framed_minheight + \fi + \fi \fi \edef\p_framed_empty{\framedparameter\c!empty}% \ifx\p_framed_empty\v!yes diff --git a/tex/context/base/mkiv/page-lin.mkvi b/tex/context/base/mkiv/page-lin.mkvi index f36b27474..a27ba5736 100644 --- a/tex/context/base/mkiv/page-lin.mkvi +++ b/tex/context/base/mkiv/page-lin.mkvi @@ -46,6 +46,10 @@ \attribute\linenumberattribute\attributeunsetvalue \to \everyforgetall +\appendtoks + \attribute\linenumberattribute \attributeunsetvalue +\to \everyinsidefloat + \newcount \linenumber % not used \newbox \b_page_lines_scratch \newcount \c_page_lines_reference diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf index 5315cf23b..9f745ce85 100644 Binary files a/tex/context/base/mkiv/status-files.pdf and b/tex/context/base/mkiv/status-files.pdf differ diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf index 338fd01eb..6a170110a 100644 Binary files a/tex/context/base/mkiv/status-lua.pdf and b/tex/context/base/mkiv/status-lua.pdf differ diff --git a/tex/context/base/mkiv/trac-deb.lua b/tex/context/base/mkiv/trac-deb.lua index c9a05f238..9f5445a7f 100644 --- a/tex/context/base/mkiv/trac-deb.lua +++ b/tex/context/base/mkiv/trac-deb.lua @@ -347,6 +347,8 @@ directives.register("system.showerror", lmx.overloaderror) -- trace_calls(n) -- end) -- indirect is needed for nilling +-- I'll make this obsolete soon. + local editor = [[scite "-open:%filename%" -goto:%linenumber%]] directives.register("system.editor",function(v) diff --git a/tex/context/base/mkiv/trac-log.lua b/tex/context/base/mkiv/trac-log.lua index 83b81c9b0..206af5668 100644 --- a/tex/context/base/mkiv/trac-log.lua +++ b/tex/context/base/mkiv/trac-log.lua @@ -1028,7 +1028,7 @@ end if tex and tex.error then function logs.texerrormessage(...) -- for the moment we put this function here - tex.error(format(...), { }) + tex.error(format(...)) end else function logs.texerrormessage(...) diff --git a/tex/context/base/mkiv/typo-krn.lua b/tex/context/base/mkiv/typo-krn.lua index 5e4792f62..a099163db 100644 --- a/tex/context/base/mkiv/typo-krn.lua +++ b/tex/context/base/mkiv/typo-krn.lua @@ -129,9 +129,6 @@ local factors = kerns.factors local gluefactor = 4 -- assumes quad = .5 enspace -kerns.keepligature = false -- just for fun (todo: control setting with key/value) -kerns.keeptogether = false -- just for fun (todo: control setting with key/value) - -- red : kept by dynamic feature -- green : kept by static feature -- blue : keep by goodie diff --git a/tex/context/interface/mkii/keys-cs.xml b/tex/context/interface/mkii/keys-cs.xml index 9d201386f..f262b27cd 100644 --- a/tex/context/interface/mkii/keys-cs.xml +++ b/tex/context/interface/mkii/keys-cs.xml @@ -140,6 +140,7 @@ + diff --git a/tex/context/interface/mkii/keys-de.xml b/tex/context/interface/mkii/keys-de.xml index 78dcbcde6..573770eef 100644 --- a/tex/context/interface/mkii/keys-de.xml +++ b/tex/context/interface/mkii/keys-de.xml @@ -140,6 +140,7 @@ + @@ -421,7 +422,7 @@ - + diff --git a/tex/context/interface/mkii/keys-it.xml b/tex/context/interface/mkii/keys-it.xml index 6edecb621..47880bd63 100644 --- a/tex/context/interface/mkii/keys-it.xml +++ b/tex/context/interface/mkii/keys-it.xml @@ -140,6 +140,7 @@ + @@ -421,7 +422,7 @@ - + diff --git a/tex/context/interface/mkiv/context-en.xml b/tex/context/interface/mkiv/context-en.xml index b29d35c1c..acd8ba5cb 100644 --- a/tex/context/interface/mkiv/context-en.xml +++ b/tex/context/interface/mkiv/context-en.xml @@ -866,23 +866,23 @@ - + - - + + - - - - - - - + + + + + + + - - + + @@ -1491,6 +1491,11 @@ + + + + + @@ -1561,6 +1566,13 @@ + + + + + + + @@ -3052,7 +3064,7 @@ - + @@ -4779,7 +4791,7 @@ - + @@ -4885,7 +4897,7 @@ - + @@ -5245,7 +5257,7 @@ - + @@ -7320,6 +7332,7 @@ + @@ -8072,6 +8085,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -10252,6 +10311,7 @@ + @@ -10389,6 +10449,7 @@ + @@ -10402,6 +10463,16 @@ + + + + + + + + + + @@ -11108,6 +11179,7 @@ + @@ -11647,7 +11719,7 @@ - + @@ -12344,7 +12416,7 @@ - + @@ -13769,21 +13841,25 @@ + + + + @@ -13800,8 +13876,9 @@ - + + @@ -13848,6 +13925,9 @@ + + + @@ -14290,6 +14370,17 @@ + + + + + + + + + + + @@ -15416,6 +15507,7 @@ + @@ -18695,6 +18787,7 @@ + @@ -18827,6 +18920,13 @@ + + + + + + + @@ -26698,6 +26798,7 @@ + @@ -34392,6 +34493,7 @@ + @@ -39630,6 +39732,24 @@ + + + + + + + + + + + + + + + + + + @@ -42414,7 +42534,7 @@ - + @@ -43376,6 +43496,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -44105,6 +44263,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -44971,7 +45231,7 @@ - + @@ -44984,7 +45244,7 @@ - + @@ -45284,19 +45544,19 @@ - + - - - + + + @@ -45305,7 +45565,11 @@ - + + + + + @@ -45568,7 +45832,7 @@ - + @@ -45577,7 +45841,7 @@ - + @@ -47059,14 +47323,18 @@ - - - + + + + + + + diff --git a/tex/context/interface/mkiv/i-backend.xml b/tex/context/interface/mkiv/i-backend.xml index ff52eed7d..d0bdb4853 100644 --- a/tex/context/interface/mkiv/i-backend.xml +++ b/tex/context/interface/mkiv/i-backend.xml @@ -18,23 +18,23 @@ - + - - + + - - - - - - - + + + + + + + - - + + diff --git a/tex/context/interface/mkiv/i-block.xml b/tex/context/interface/mkiv/i-block.xml index 0bd0ef51b..3416a96ee 100644 --- a/tex/context/interface/mkiv/i-block.xml +++ b/tex/context/interface/mkiv/i-block.xml @@ -63,6 +63,7 @@ + @@ -119,4 +120,10 @@ + + + + + + diff --git a/tex/context/interface/mkiv/i-buffer.xml b/tex/context/interface/mkiv/i-buffer.xml index 0c94b7828..f08cb8ca4 100644 --- a/tex/context/interface/mkiv/i-buffer.xml +++ b/tex/context/interface/mkiv/i-buffer.xml @@ -101,7 +101,7 @@ - + diff --git a/tex/context/interface/mkiv/i-color.xml b/tex/context/interface/mkiv/i-color.xml index 80da11f3b..4dd76d0b3 100644 --- a/tex/context/interface/mkiv/i-color.xml +++ b/tex/context/interface/mkiv/i-color.xml @@ -263,7 +263,7 @@ - + @@ -366,7 +366,7 @@ - + diff --git a/tex/context/interface/mkiv/i-columns.xml b/tex/context/interface/mkiv/i-columns.xml index 9fdd209c0..b89bd5845 100644 --- a/tex/context/interface/mkiv/i-columns.xml +++ b/tex/context/interface/mkiv/i-columns.xml @@ -73,7 +73,7 @@ - + diff --git a/tex/context/interface/mkiv/i-common-argument.xml b/tex/context/interface/mkiv/i-common-argument.xml index 787475e8b..de000148b 100644 --- a/tex/context/interface/mkiv/i-common-argument.xml +++ b/tex/context/interface/mkiv/i-common-argument.xml @@ -532,4 +532,4 @@ - + \ No newline at end of file diff --git a/tex/context/interface/mkiv/i-common-value.xml b/tex/context/interface/mkiv/i-common-value.xml index ba90de3be..a6884185f 100644 --- a/tex/context/interface/mkiv/i-common-value.xml +++ b/tex/context/interface/mkiv/i-common-value.xml @@ -315,6 +315,41 @@ + diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf index ae92c7a6b..2f56f7357 100644 Binary files a/tex/context/interface/mkiv/i-context.pdf and b/tex/context/interface/mkiv/i-context.pdf differ diff --git a/tex/context/interface/mkiv/i-context.xml b/tex/context/interface/mkiv/i-context.xml index da34d4517..01adac436 100644 --- a/tex/context/interface/mkiv/i-context.xml +++ b/tex/context/interface/mkiv/i-context.xml @@ -227,6 +227,7 @@ + diff --git a/tex/context/interface/mkiv/i-delimitedtext.xml b/tex/context/interface/mkiv/i-delimitedtext.xml index c34052644..ce1767b1c 100644 --- a/tex/context/interface/mkiv/i-delimitedtext.xml +++ b/tex/context/interface/mkiv/i-delimitedtext.xml @@ -16,7 +16,10 @@ - + + + + diff --git a/tex/context/interface/mkiv/i-document.xml b/tex/context/interface/mkiv/i-document.xml index fcd9e040b..178f7e9fe 100644 --- a/tex/context/interface/mkiv/i-document.xml +++ b/tex/context/interface/mkiv/i-document.xml @@ -218,4 +218,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tex/context/interface/mkiv/i-floats.xml b/tex/context/interface/mkiv/i-floats.xml index 4b26b9e95..77a0f00a1 100644 --- a/tex/context/interface/mkiv/i-floats.xml +++ b/tex/context/interface/mkiv/i-floats.xml @@ -206,6 +206,7 @@ + @@ -495,6 +496,7 @@ + @@ -508,6 +510,29 @@ + + + + + + + + + + + @@ -975,4 +1000,6 @@ + + diff --git a/tex/context/interface/mkiv/i-fonts.xml b/tex/context/interface/mkiv/i-fonts.xml index 03bdb2a7e..721bfca63 100644 --- a/tex/context/interface/mkiv/i-fonts.xml +++ b/tex/context/interface/mkiv/i-fonts.xml @@ -340,7 +340,7 @@ - + @@ -965,7 +965,7 @@ - + diff --git a/tex/context/interface/mkiv/i-framed.xml b/tex/context/interface/mkiv/i-framed.xml index cf9ffda0a..5e96ba80d 100644 --- a/tex/context/interface/mkiv/i-framed.xml +++ b/tex/context/interface/mkiv/i-framed.xml @@ -57,21 +57,25 @@ + + + + @@ -88,8 +92,9 @@ - + + @@ -133,6 +138,9 @@ + + + @@ -628,4 +636,12 @@ - + + + + + + + + + \ No newline at end of file diff --git a/tex/context/interface/mkiv/i-hspace.xml b/tex/context/interface/mkiv/i-hspace.xml index cc3c32f3d..31c215864 100644 --- a/tex/context/interface/mkiv/i-hspace.xml +++ b/tex/context/interface/mkiv/i-hspace.xml @@ -35,6 +35,7 @@ + diff --git a/tex/context/interface/mkiv/i-language.xml b/tex/context/interface/mkiv/i-language.xml index e682aec3d..de8835a79 100644 --- a/tex/context/interface/mkiv/i-language.xml +++ b/tex/context/interface/mkiv/i-language.xml @@ -64,6 +64,7 @@ + @@ -177,6 +178,12 @@ + + + + + + diff --git a/tex/context/interface/mkiv/i-pagegrid.xml b/tex/context/interface/mkiv/i-pagegrid.xml index 3d08d8b8d..f25e72f72 100644 --- a/tex/context/interface/mkiv/i-pagegrid.xml +++ b/tex/context/interface/mkiv/i-pagegrid.xml @@ -32,7 +32,10 @@ - + + + + @@ -75,7 +78,10 @@ - + + + + @@ -86,6 +92,7 @@ + @@ -93,6 +100,7 @@ + diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf index f06288b82..231db10fe 100644 Binary files a/tex/context/interface/mkiv/i-readme.pdf and b/tex/context/interface/mkiv/i-readme.pdf differ diff --git a/tex/context/interface/mkiv/i-ruby.xml b/tex/context/interface/mkiv/i-ruby.xml index 10bcff22e..4422029b8 100644 --- a/tex/context/interface/mkiv/i-ruby.xml +++ b/tex/context/interface/mkiv/i-ruby.xml @@ -22,6 +22,7 @@ + diff --git a/tex/context/interface/mkiv/i-startstop.xml b/tex/context/interface/mkiv/i-startstop.xml index 3df32a516..ba0abb0b7 100644 --- a/tex/context/interface/mkiv/i-startstop.xml +++ b/tex/context/interface/mkiv/i-startstop.xml @@ -97,4 +97,4 @@ - + \ No newline at end of file diff --git a/tex/context/interface/mkiv/i-system.xml b/tex/context/interface/mkiv/i-system.xml index e5aa28ea4..c8abff238 100644 --- a/tex/context/interface/mkiv/i-system.xml +++ b/tex/context/interface/mkiv/i-system.xml @@ -1840,6 +1840,22 @@ + + + + + + + + + + + + + + + + diff --git a/tex/context/interface/mkiv/i-tagging.xml b/tex/context/interface/mkiv/i-tagging.xml index a7f94fcd2..d07b32ec1 100644 --- a/tex/context/interface/mkiv/i-tagging.xml +++ b/tex/context/interface/mkiv/i-tagging.xml @@ -25,7 +25,7 @@ - + diff --git a/tex/context/interface/mkiv/i-token.xml b/tex/context/interface/mkiv/i-token.xml index 129f472ba..09e2ad3d6 100644 --- a/tex/context/interface/mkiv/i-token.xml +++ b/tex/context/interface/mkiv/i-token.xml @@ -28,4 +28,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tex/context/interface/mkiv/i-unit.xml b/tex/context/interface/mkiv/i-unit.xml index 9efa452eb..c8092a4ed 100644 --- a/tex/context/interface/mkiv/i-unit.xml +++ b/tex/context/interface/mkiv/i-unit.xml @@ -125,4 +125,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/tex/context/interface/mkiv/i-userdata.xml b/tex/context/interface/mkiv/i-userdata.xml new file mode 100644 index 000000000..e9617f0bc --- /dev/null +++ b/tex/context/interface/mkiv/i-userdata.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tex/context/interface/mkiv/i-verbatim.xml b/tex/context/interface/mkiv/i-verbatim.xml index e8abc1f66..830b8bb11 100644 --- a/tex/context/interface/mkiv/i-verbatim.xml +++ b/tex/context/interface/mkiv/i-verbatim.xml @@ -321,7 +321,7 @@ - + @@ -329,7 +329,7 @@ - + diff --git a/tex/context/interface/mkiv/i-visualizer.xml b/tex/context/interface/mkiv/i-visualizer.xml index cf9d22e22..81d02f4fb 100644 --- a/tex/context/interface/mkiv/i-visualizer.xml +++ b/tex/context/interface/mkiv/i-visualizer.xml @@ -112,19 +112,19 @@ - + - - - + + + @@ -133,7 +133,11 @@ - + + + + + diff --git a/tex/context/interface/mkiv/i-whitespace.xml b/tex/context/interface/mkiv/i-whitespace.xml index 83547fea5..a44b08f1d 100644 --- a/tex/context/interface/mkiv/i-whitespace.xml +++ b/tex/context/interface/mkiv/i-whitespace.xml @@ -39,7 +39,7 @@ - + @@ -50,7 +50,7 @@ - + diff --git a/tex/context/interface/mkiv/i-xtable.xml b/tex/context/interface/mkiv/i-xtable.xml index 5172f885f..7ee0df3f2 100644 --- a/tex/context/interface/mkiv/i-xtable.xml +++ b/tex/context/interface/mkiv/i-xtable.xml @@ -155,15 +155,33 @@ + + - + + + + + + diff --git a/tex/context/modules/mkiv/s-fonts-shapes.lua b/tex/context/modules/mkiv/s-fonts-shapes.lua index 4fc810a92..868c22da1 100644 --- a/tex/context/modules/mkiv/s-fonts-shapes.lua +++ b/tex/context/modules/mkiv/s-fonts-shapes.lua @@ -122,7 +122,7 @@ local function showglyphshape(specification) l[i] = formatters["((%s,%s) shifted (%s,%s))"](xsign*k*factor,ysign*h*factor,dx,dy) end context("draw ((%s,%s) shifted (%s,%s))--%s dashed (evenly scaled 1/16) withcolor .5white;", xsign*v[1].kern*factor,lly,dx,dy,l[1]) - context("draw laddered (%..t) withcolor .5white ;",l) + context("draw laddered (%..t) withcolor .5white ;",l) -- why not "--" context("draw ((%s,%s) shifted (%s,%s))--%s dashed (evenly scaled 1/16) withcolor .5white;", xsign*v[#v].kern*factor,ury,dx,dy,l[#l]) for i=1,n do context("draw %s withcolor blue withpen pencircle scaled 2lw ;",l[i]) diff --git a/tex/context/modules/mkiv/s-fonts-shapes.mkiv b/tex/context/modules/mkiv/s-fonts-shapes.mkiv index 05515ae37..90b9c1f64 100644 --- a/tex/context/modules/mkiv/s-fonts-shapes.mkiv +++ b/tex/context/modules/mkiv/s-fonts-shapes.mkiv @@ -106,6 +106,9 @@ % \startTEXpage \ShowGlyphShape{simplenaskhi}{100bp}{0xF0299} \stopTEXpage % \startTEXpage \ShowGlyphShape{simplenaskhi}{100bp}{NameMe.1190} \stopTEXpage + \startTEXpage[offset=0pt]\ShowGlyphShape{file:stix2math.otf}{20bp}{0x1D44A}\stopTEXpage + \startTEXpage[offset=0pt]\ShowGlyphShape{file:stix2math.otf}{20bp}{0x1D44C}\stopTEXpage + % \startTEXpage[offset=0pt]\ShowGlyphShape{name:cambria-math}{20bp}{0x00066}\stopTEXpage % \startTEXpage[offset=0pt]\ShowGlyphShape{name:cambria-math}{20bp}{0x1D453}\stopTEXpage % \startTEXpage[offset=0pt]\ShowGlyphShape{name:cambria-math}{20bp}{0x1D43F}\stopTEXpage @@ -120,7 +123,8 @@ % \startTEXpage[offset=0pt]\ShowGlyphShape{file:husayninotebold.ttf}{50bp}{0xF034A}\stopTEXpage % \startTEXpage[offset=0pt]\ShowGlyphShape{file:husayninotebold.ttf}{50bp}{0x006DD}\stopTEXpage -\startTEXpage[offset=0pt]\ShowGlyphShape{file:arabtype.ttf}{50bp}{0x0FCA1}\stopTEXpage +% \startTEXpage[offset=0pt]\ShowGlyphShape{file:husayninotebold.ttf}{50bp}{0x006DD}\stopTEXpage +% \startTEXpage[offset=0pt]\ShowGlyphShape{file:arabtype.ttf}{50bp}{0x0FCA1}\stopTEXpage % \showallglyphshapes[name=name:cambria-math,size=100bp] % \showallglyphshapes[name=name:arabtype,size=100bp] diff --git a/tex/context/modules/mkiv/s-fonts-variable.mkiv b/tex/context/modules/mkiv/s-fonts-variable.mkiv index bc4b4a9b6..2cd612c75 100644 --- a/tex/context/modules/mkiv/s-fonts-variable.mkiv +++ b/tex/context/modules/mkiv/s-fonts-variable.mkiv @@ -91,9 +91,9 @@ % \showfontvariations % [font=file:LibreFranklinGX-Romans.ttf] -% \showfontvariations -% [font=file:Zycon.ttf, -% sample={\getbuffer[zycon]}] + % \showfontvariations + % [font=file:Zycon.ttf, + % sample={\getbuffer[zycon]}] % \showfontvariations % [font=file:kairossansvariable.ttf] @@ -104,8 +104,8 @@ % \showfontvariations % [font=file:AmstelvarAlpha-VF.ttf] - \showfontvariations - [font=file:bahnschrift.ttf] + % \showfontvariations + % [font=file:bahnschrift.ttf] % \showfontvariations % [font=file:sitka.ttc] diff --git a/tex/generic/context/luatex/luatex-basics-gen.lua b/tex/generic/context/luatex/luatex-basics-gen.lua index ee0367fa4..3959ca022 100644 --- a/tex/generic/context/luatex/luatex-basics-gen.lua +++ b/tex/generic/context/luatex/luatex-basics-gen.lua @@ -414,3 +414,66 @@ if not number.idiv then return floor(i/d) -- i//d in 5.3 end end + +-- hook into unicode + +local u = unicode and unicode.utf8 + +if u then + + utf.lower = u.lower + utf.upper = u.upper + utf.char = u.char + utf.byte = u.byte + utf.len = u.len + + -- needed on font-* + + if lpeg.setutfcasers then + lpeg.setutfcasers(u.lower,u.upper) + end + + -- needed on font-otr + + local bytepairs = string.bytepairs + local utfchar = utf.char + local concat = table.concat + + function utf.utf16_to_utf8_be(s) + if not s then + return nil + elseif s == "" then + return "" + end + local result, r, more = { }, 0, 0 + for left, right in bytepairs(s) do + if right then + local now = 256*left + right + if more > 0 then + now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 + more = 0 + r = r + 1 + result[r] = utfchar(now) + elseif now >= 0xD800 and now <= 0xDBFF then + more = now + else + r = r + 1 + result[r] = utfchar(now) + end + end + end + return concat(result) + end + + local characters = string.utfcharacters + + function utf.split(str) + local t, n = { }, 0 + for s in characters(str) do + n = n + 1 + t[n] = s + end + return t + end + +end diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index d339e9bff..4c305fb9e 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 : 12/07/18 19:37:06 +-- merge date : 12/17/18 16:39:37 do -- begin closure to overcome local limits and interference @@ -554,64 +554,6 @@ function lpeg.counter(pattern,action) return function(str) n=0;lpegmatch(pattern,str);return n end end end -utf=utf or {} -local utfcharacters=utf and utf.characters or string.utfcharacters -local utfgmatch=utf and utf.gmatch -local utfchar=utf and utf.char -lpeg.UP=lpeg.P -if utfcharacters then - function lpeg.US(str) - local p=P(false) - for uc in utfcharacters(str) do - p=p+P(uc) - end - return p - end -elseif utfgmatch then - function lpeg.US(str) - local p=P(false) - for uc in utfgmatch(str,".") do - p=p+P(uc) - end - return p - end -else - function lpeg.US(str) - local p=P(false) - local f=function(uc) - p=p+P(uc) - end - lpegmatch((utf8char/f)^0,str) - return p - end -end -local range=utf8byte*utf8byte+Cc(false) -function lpeg.UR(str,more) - local first,last - if type(str)=="number" then - first=str - last=more or first - else - first,last=lpegmatch(range,str) - if not last then - return P(str) - end - end - if first==last then - return P(str) - elseif utfchar and (last-first<8) then - local p=P(false) - for i=first,last do - p=p+P(utfchar(i)) - end - return p - else - local f=function(b) - return b>=first and b<=last - end - return utf8byte/f - end -end function lpeg.is_lpeg(p) return p and lpegtype(p)=="pattern" end @@ -3090,697 +3032,6 @@ end -- closure do -- begin closure to overcome local limits and interference -if not modules then modules={} end modules ['l-unicode']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -utf=utf or {} -unicode=nil -utf.characters=utf.characters or string.utfcharacters -utf.values=utf.values or string.utfvalues -local type=type -local char,byte,format,sub,gmatch=string.char,string.byte,string.format,string.sub,string.gmatch -local concat=table.concat -local P,C,R,Cs,Ct,Cmt,Cc,Carg,Cp=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Ct,lpeg.Cmt,lpeg.Cc,lpeg.Carg,lpeg.Cp -local lpegmatch=lpeg.match -local patterns=lpeg.patterns -local tabletopattern=lpeg.utfchartabletopattern -local bytepairs=string.bytepairs -local finder=lpeg.finder -local replacer=lpeg.replacer -local utfvalues=utf.values -local utfgmatch=utf.gmatch -local p_utftype=patterns.utftype -local p_utfstricttype=patterns.utfstricttype -local p_utfoffset=patterns.utfoffset -local p_utf8char=patterns.utf8character -local p_utf8byte=patterns.utf8byte -local p_utfbom=patterns.utfbom -local p_newline=patterns.newline -local p_whitespace=patterns.whitespace -if not utf.char then - utf.char=string.utfcharacter or (utf8 and utf8.char) - if not utf.char then - local char=string.char - if bit32 then - local rshift=bit32.rshift - function utf.char(n) - if n<0x80 then - return char(n) - elseif n<0x800 then - return char( - 0xC0+rshift(n,6), - 0x80+(n%0x40) - ) - elseif n<0x10000 then - return char( - 0xE0+rshift(n,12), - 0x80+(rshift(n,6)%0x40), - 0x80+(n%0x40) - ) - elseif n<0x200000 then - return char( - 0xF0+rshift(n,18), - 0x80+(rshift(n,12)%0x40), - 0x80+(rshift(n,6)%0x40), - 0x80+(n%0x40) - ) - else - return "" - end - end - else - local floor=math.floor - function utf.char(n) - if n<0x80 then - return char(n) - elseif n<0x800 then - return char( - 0xC0+floor(n/0x40), - 0x80+(n%0x40) - ) - elseif n<0x10000 then - return char( - 0xE0+floor(n/0x1000), - 0x80+(floor(n/0x40)%0x40), - 0x80+(n%0x40) - ) - elseif n<0x200000 then - return char( - 0xF0+floor(n/0x40000), - 0x80+(floor(n/0x1000)%0x40), - 0x80+(floor(n/0x40)%0x40), - 0x80+(n%0x40) - ) - else - return "" - end - end - end - end -end -if not utf.byte then - utf.byte=string.utfvalue or (utf8 and utf8.codepoint) - if not utf.byte then - local utf8byte=patterns.utf8byte - function utf.byte(c) - return lpegmatch(utf8byte,c) - end - end -end -local utfchar,utfbyte=utf.char,utf.byte -function utf.filetype(data) - return data and lpegmatch(p_utftype,data) or "unknown" -end -local toentities=Cs ( - ( - patterns.utf8one+( - patterns.utf8two+patterns.utf8three+patterns.utf8four - )/function(s) local b=utfbyte(s) if b<127 then return s else return format("&#%X;",b) end end - )^0 -) -patterns.toentities=toentities -function utf.toentities(str) - return lpegmatch(toentities,str) -end -local one=P(1) -local two=C(1)*C(1) -local four=C(R(utfchar(0xD8),utfchar(0xFF)))*C(1)*C(1)*C(1) -local pattern=P("\254\255")*Cs(( - four/function(a,b,c,d) - local ab=0xFF*byte(a)+byte(b) - local cd=0xFF*byte(c)+byte(d) - return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000) - end+two/function(a,b) - return utfchar(byte(a)*256+byte(b)) - end+one - )^1 )+P("\255\254")*Cs(( - four/function(b,a,d,c) - local ab=0xFF*byte(a)+byte(b) - local cd=0xFF*byte(c)+byte(d) - return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000) - end+two/function(b,a) - return utfchar(byte(a)*256+byte(b)) - end+one - )^1 ) -function string.toutf(s) - return lpegmatch(pattern,s) or s -end -local validatedutf=Cs ( - ( - patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four+P(1)/"�" - )^0 -) -patterns.validatedutf=validatedutf -function utf.is_valid(str) - return type(str)=="string" and lpegmatch(validatedutf,str) or false -end -if not utf.len then - utf.len=string.utflength or (utf8 and utf8.len) - if not utf.len then - local n,f=0,1 - local utfcharcounter=patterns.utfbom^-1*Cmt ( - Cc(1)*patterns.utf8one^1+Cc(2)*patterns.utf8two^1+Cc(3)*patterns.utf8three^1+Cc(4)*patterns.utf8four^1, - function(_,t,d) - n=n+(t-f)/d - f=t - return true - end - )^0 - function utf.len(str) - n,f=0,1 - lpegmatch(utfcharcounter,str or "") - return n - end - end -end -utf.length=utf.len -if not utf.sub then - local utflength=utf.length - local b,e,n,first,last=0,0,0,0,0 - local function slide_zero(s,p) - n=n+1 - if n>=last then - e=p-1 - else - return p - end - end - local function slide_one(s,p) - n=n+1 - if n==first then - b=p - end - if n>=last then - e=p-1 - else - return p - end - end - local function slide_two(s,p) - n=n+1 - if n==first then - b=p - else - return true - end - end - local pattern_zero=Cmt(p_utf8char,slide_zero)^0 - local pattern_one=Cmt(p_utf8char,slide_one )^0 - local pattern_two=Cmt(p_utf8char,slide_two )^0 - local pattern_first=C(patterns.utf8character) - function utf.sub(str,start,stop) - if not start then - return str - end - if start==0 then - start=1 - end - if not stop then - if start<0 then - local l=utflength(str) - start=l+start - else - start=start-1 - end - b,n,first=0,0,start - lpegmatch(pattern_two,str) - if n>=first then - return sub(str,b) - else - return "" - end - end - if start<0 or stop<0 then - local l=utf.length(str) - if start<0 then - start=l+start - if start<=0 then - start=1 - else - start=start+1 - end - end - if stop<0 then - stop=l+stop - if stop==0 then - stop=1 - else - stop=stop+1 - end - end - end - if start==1 and stop==1 then - return lpegmatch(pattern_first,str) or "" - elseif start>stop then - return "" - elseif start>1 then - b,e,n,first,last=0,0,0,start-1,stop - lpegmatch(pattern_one,str) - if n>=first and e==0 then - e=#str - end - return sub(str,b,e) - else - b,e,n,last=1,0,0,stop - lpegmatch(pattern_zero,str) - if e==0 then - e=#str - end - return sub(str,b,e) - end - end -end -function utf.remapper(mapping,option,action) - local variant=type(mapping) - if variant=="table" then - action=action or mapping - if option=="dynamic" then - local pattern=false - table.setmetatablenewindex(mapping,function(t,k,v) rawset(t,k,v) pattern=false end) - return function(str) - if not str or str=="" then - return "" - else - if not pattern then - pattern=Cs((tabletopattern(mapping)/action+p_utf8char)^0) - end - return lpegmatch(pattern,str) - end - end - elseif option=="pattern" then - return Cs((tabletopattern(mapping)/action+p_utf8char)^0) - else - local pattern=Cs((tabletopattern(mapping)/action+p_utf8char)^0) - return function(str) - if not str or str=="" then - return "" - else - return lpegmatch(pattern,str) - end - end,pattern - end - elseif variant=="function" then - if option=="pattern" then - return Cs((p_utf8char/mapping+p_utf8char)^0) - else - local pattern=Cs((p_utf8char/mapping+p_utf8char)^0) - return function(str) - if not str or str=="" then - return "" - else - return lpegmatch(pattern,str) - end - end,pattern - end - else - return function(str) - return str or "" - end - end -end -function utf.replacer(t) - local r=replacer(t,false,false,true) - return function(str) - return lpegmatch(r,str) - end -end -function utf.subtituter(t) - local f=finder (t) - local r=replacer(t,false,false,true) - return function(str) - local i=lpegmatch(f,str) - if not i then - return str - elseif i>#str then - return str - else - return lpegmatch(r,str) - end - end -end -local utflinesplitter=p_utfbom^-1*lpeg.tsplitat(p_newline) -local utfcharsplitter_ows=p_utfbom^-1*Ct(C(p_utf8char)^0) -local utfcharsplitter_iws=p_utfbom^-1*Ct((p_whitespace^1+C(p_utf8char))^0) -local utfcharsplitter_raw=Ct(C(p_utf8char)^0) -patterns.utflinesplitter=utflinesplitter -function utf.splitlines(str) - return lpegmatch(utflinesplitter,str or "") -end -function utf.split(str,ignorewhitespace) - if ignorewhitespace then - return lpegmatch(utfcharsplitter_iws,str or "") - else - return lpegmatch(utfcharsplitter_ows,str or "") - end -end -function utf.totable(str) - return lpegmatch(utfcharsplitter_raw,str) -end -function utf.magic(f) - local str=f:read(4) or "" - local off=lpegmatch(p_utfoffset,str) - if off<4 then - f:seek('set',off) - end - return lpegmatch(p_utftype,str) -end -local utf16_to_utf8_be,utf16_to_utf8_le -local utf32_to_utf8_be,utf32_to_utf8_le -local utf_16_be_getbom=patterns.utfbom_16_be^-1 -local utf_16_le_getbom=patterns.utfbom_16_le^-1 -local utf_32_be_getbom=patterns.utfbom_32_be^-1 -local utf_32_le_getbom=patterns.utfbom_32_le^-1 -local utf_16_be_linesplitter=utf_16_be_getbom*lpeg.tsplitat(patterns.utf_16_be_nl) -local utf_16_le_linesplitter=utf_16_le_getbom*lpeg.tsplitat(patterns.utf_16_le_nl) -local utf_32_be_linesplitter=utf_32_be_getbom*lpeg.tsplitat(patterns.utf_32_be_nl) -local utf_32_le_linesplitter=utf_32_le_getbom*lpeg.tsplitat(patterns.utf_32_le_nl) -local more=0 -local p_utf16_to_utf8_be=C(1)*C(1)/function(left,right) - local now=256*byte(left)+byte(right) - if more>0 then - now=(more-0xD800)*0x400+(now-0xDC00)+0x10000 - more=0 - return utfchar(now) - elseif now>=0xD800 and now<=0xDBFF then - more=now - return "" - else - return utfchar(now) - end -end -local p_utf16_to_utf8_le=C(1)*C(1)/function(right,left) - local now=256*byte(left)+byte(right) - if more>0 then - now=(more-0xD800)*0x400+(now-0xDC00)+0x10000 - more=0 - return utfchar(now) - elseif now>=0xD800 and now<=0xDBFF then - more=now - return "" - else - return utfchar(now) - end -end -local p_utf32_to_utf8_be=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d) - return utfchar(256*256*256*byte(a)+256*256*byte(b)+256*byte(c)+byte(d)) -end -local p_utf32_to_utf8_le=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d) - return utfchar(256*256*256*byte(d)+256*256*byte(c)+256*byte(b)+byte(a)) -end -p_utf16_to_utf8_be=P(true)/function() more=0 end*utf_16_be_getbom*Cs(p_utf16_to_utf8_be^0) -p_utf16_to_utf8_le=P(true)/function() more=0 end*utf_16_le_getbom*Cs(p_utf16_to_utf8_le^0) -p_utf32_to_utf8_be=P(true)/function() more=0 end*utf_32_be_getbom*Cs(p_utf32_to_utf8_be^0) -p_utf32_to_utf8_le=P(true)/function() more=0 end*utf_32_le_getbom*Cs(p_utf32_to_utf8_le^0) -patterns.utf16_to_utf8_be=p_utf16_to_utf8_be -patterns.utf16_to_utf8_le=p_utf16_to_utf8_le -patterns.utf32_to_utf8_be=p_utf32_to_utf8_be -patterns.utf32_to_utf8_le=p_utf32_to_utf8_le -utf16_to_utf8_be=function(s) - if s and s~="" then - return lpegmatch(p_utf16_to_utf8_be,s) - else - return s - end -end -local utf16_to_utf8_be_t=function(t) - if not t then - return nil - elseif type(t)=="string" then - t=lpegmatch(utf_16_be_linesplitter,t) - end - for i=1,#t do - local s=t[i] - if s~="" then - t[i]=lpegmatch(p_utf16_to_utf8_be,s) - end - end - return t -end -utf16_to_utf8_le=function(s) - if s and s~="" then - return lpegmatch(p_utf16_to_utf8_le,s) - else - return s - end -end -local utf16_to_utf8_le_t=function(t) - if not t then - return nil - elseif type(t)=="string" then - t=lpegmatch(utf_16_le_linesplitter,t) - end - for i=1,#t do - local s=t[i] - if s~="" then - t[i]=lpegmatch(p_utf16_to_utf8_le,s) - end - end - return t -end -utf32_to_utf8_be=function(s) - if s and s~="" then - return lpegmatch(p_utf32_to_utf8_be,s) - else - return s - end -end -local utf32_to_utf8_be_t=function(t) - if not t then - return nil - elseif type(t)=="string" then - t=lpegmatch(utf_32_be_linesplitter,t) - end - for i=1,#t do - local s=t[i] - if s~="" then - t[i]=lpegmatch(p_utf32_to_utf8_be,s) - end - end - return t -end -utf32_to_utf8_le=function(s) - if s and s~="" then - return lpegmatch(p_utf32_to_utf8_le,s) - else - return s - end -end -local utf32_to_utf8_le_t=function(t) - if not t then - return nil - elseif type(t)=="string" then - t=lpegmatch(utf_32_le_linesplitter,t) - end - for i=1,#t do - local s=t[i] - if s~="" then - t[i]=lpegmatch(p_utf32_to_utf8_le,s) - end - end - return t -end -utf.utf16_to_utf8_le_t=utf16_to_utf8_le_t -utf.utf16_to_utf8_be_t=utf16_to_utf8_be_t -utf.utf32_to_utf8_le_t=utf32_to_utf8_le_t -utf.utf32_to_utf8_be_t=utf32_to_utf8_be_t -utf.utf16_to_utf8_le=utf16_to_utf8_le -utf.utf16_to_utf8_be=utf16_to_utf8_be -utf.utf32_to_utf8_le=utf32_to_utf8_le -utf.utf32_to_utf8_be=utf32_to_utf8_be -function utf.utf8_to_utf8_t(t) - return type(t)=="string" and lpegmatch(utflinesplitter,t) or t -end -function utf.utf16_to_utf8_t(t,endian) - return endian and utf16_to_utf8_be_t(t) or utf16_to_utf8_le_t(t) or t -end -function utf.utf32_to_utf8_t(t,endian) - return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t -end -local function little(b) - if b<0x10000 then - return char(b%256,rshift(b,8)) - else - b=b-0x10000 - local b1=rshift(b,10)+0xD800 - local b2=b%1024+0xDC00 - return char(b1%256,rshift(b1,8),b2%256,rshift(b2,8)) - end -end -local function big(b) - if b<0x10000 then - return char(rshift(b,8),b%256) - else - b=b-0x10000 - local b1=rshift(b,10)+0xD800 - local b2=b%1024+0xDC00 - return char(rshift(b1,8),b1%256,rshift(b2,8),b2%256) - end -end -local l_remap=Cs((p_utf8byte/little+P(1)/"")^0) -local b_remap=Cs((p_utf8byte/big+P(1)/"")^0) -local function utf8_to_utf16_be(str,nobom) - if nobom then - return lpegmatch(b_remap,str) - else - return char(254,255)..lpegmatch(b_remap,str) - end -end -local function utf8_to_utf16_le(str,nobom) - if nobom then - return lpegmatch(l_remap,str) - else - return char(255,254)..lpegmatch(l_remap,str) - end -end -utf.utf8_to_utf16_be=utf8_to_utf16_be -utf.utf8_to_utf16_le=utf8_to_utf16_le -function utf.utf8_to_utf16(str,littleendian,nobom) - if littleendian then - return utf8_to_utf16_le(str,nobom) - else - return utf8_to_utf16_be(str,nobom) - end -end -local pattern=Cs ( - (p_utf8byte/function(unicode ) return format("0x%04X",unicode) end)*(p_utf8byte*Carg(1)/function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0 -) -function utf.tocodes(str,separator) - return lpegmatch(pattern,str,1,separator or " ") -end -function utf.ustring(s) - return format("U+%05X",type(s)=="number" and s or utfbyte(s)) -end -function utf.xstring(s) - return format("0x%05X",type(s)=="number" and s or utfbyte(s)) -end -function utf.toeight(str) - if not str or str=="" then - return nil - end - local utftype=lpegmatch(p_utfstricttype,str) - if utftype=="utf-8" then - return sub(str,4) - elseif utftype=="utf-16-be" then - return utf16_to_utf8_be(str) - elseif utftype=="utf-16-le" then - return utf16_to_utf8_le(str) - else - return str - end -end -local p_nany=p_utf8char/"" -if utfgmatch then - function utf.count(str,what) - if type(what)=="string" then - local n=0 - for _ in utfgmatch(str,what) do - n=n+1 - end - return n - else - return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str) - end - end -else - local cache={} - function utf.count(str,what) - if type(what)=="string" then - local p=cache[what] - if not p then - p=Cs((P(what)/" "+p_nany)^0) - cache[p]=p - end - return #lpegmatch(p,str) - else - return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str) - end - end -end -if not utf.characters then - function utf.characters(str) - return gmatch(str,".[\128-\191]*") - end - string.utfcharacters=utf.characters -end -if not utf.values then - local find=string.find - local dummy=function() - end - function utf.values(str) - local n=#str - if n==0 then - return dummy - elseif n==1 then - return function() return utfbyte(str) end - else - local p=1 - return function() - local b,e=find(str,".[\128-\191]*",p) - if b then - p=e+1 - return utfbyte(sub(str,b,e)) - end - end - end - end - string.utfvalues=utf.values -end -function utf.chrlen(u) - return - (u<0x80 and 1) or - (u<0xE0 and 2) or - (u<0xF0 and 3) or - (u<0xF8 and 4) or - (u<0xFC and 5) or - (u<0xFE and 6) or 0 -end -if bit32 then - local extract=bit32.extract - local char=string.char - function utf.toutf32string(n) - if n<=0xFF then - return - char(n).."\000\000\000" - elseif n<=0xFFFF then - return - char(extract(n,0,8))..char(extract(n,8,8)).."\000\000" - elseif n<=0xFFFFFF then - return - char(extract(n,0,8))..char(extract(n,8,8))..char(extract(n,16,8)).."\000" - else - return - char(extract(n,0,8))..char(extract(n,8,8))..char(extract(n,16,8))..char(extract(n,24,8)) - end - end -end -local len=utf.len -local rep=rep -function string.utfpadd(s,n) - if n and n~=0 then - local l=len(s) - if n>0 then - local d=n-l - if d>0 then - return rep(c or " ",d)..s - end - else - local d=- n-l - if d>0 then - return s..rep(c or " ",d) - end - end - end - return s -end - -end -- closure - -do -- begin closure to overcome local limits and interference - if not modules then modules={} end modules ['util-str']={ version=1.001, comment="companion to luat-lib.mkiv", @@ -5284,6 +4535,54 @@ if not number.idiv then return floor(i/d) end end +local u=unicode and unicode.utf8 +if u then + utf.lower=u.lower + utf.upper=u.upper + utf.char=u.char + utf.byte=u.byte + utf.len=u.len + if lpeg.setutfcasers then + lpeg.setutfcasers(u.lower,u.upper) + end + local bytepairs=string.bytepairs + local utfchar=utf.char + local concat=table.concat + function utf.utf16_to_utf8_be(s) + if not s then + return nil + elseif s=="" then + return "" + end + local result,r,more={},0,0 + for left,right in bytepairs(s) do + if right then + local now=256*left+right + if more>0 then + now=(more-0xD800)*0x400+(now-0xDC00)+0x10000 + more=0 + r=r+1 + result[r]=utfchar(now) + elseif now>=0xD800 and now<=0xDBFF then + more=now + else + r=r+1 + result[r]=utfchar(now) + end + end + end + return concat(result) + end + local characters=string.utfcharacters + function utf.split(str) + local t,n={},0 + for s in characters(str) do + n=n+1 + t[n]=s + end + return t + end +end end -- closure @@ -11172,7 +10471,7 @@ if not modules then modules={} end modules ['font-vfc']={ copyright="PRAGMA ADE / ConTeXt Development Team", license="see context related readme files" } -local select=select +local select,type=select,type local insert=table.insert local fonts=fonts local helpers=fonts.helpers @@ -11184,7 +10483,7 @@ local dummy={ "comment" } function helpers.prependcommands(commands,...) insert(commands,1,push) for i=select("#",...),1,-1 do - local s=select(i,...) + local s=(select(i,...)) if s then insert(commands,1,s) end @@ -11196,7 +10495,29 @@ function helpers.appendcommands(commands,...) insert(commands,1,push) insert(commands,pop) for i=1,select("#",...) do - local s=select(i,...) + local s=(select(i,...)) + if s then + insert(commands,s) + end + end + return commands +end +function helpers.prependcommandtable(commands,t) + insert(commands,1,push) + for i=#t,1,-1 do + local s=t[i] + if s then + insert(commands,1,s) + end + end + insert(commands,pop) + return commands +end +function helpers.appendcommandtable(commands,t) + insert(commands,1,push) + insert(commands,pop) + for i=1,#t do + local s=t[i] if s then insert(commands,s) end diff --git a/tex/generic/context/luatex/luatex-fonts.lua b/tex/generic/context/luatex/luatex-fonts.lua index b869efc56..69908dfcc 100644 --- a/tex/generic/context/luatex/luatex-fonts.lua +++ b/tex/generic/context/luatex/luatex-fonts.lua @@ -206,7 +206,6 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then loadmodule("l-file.lua") loadmodule("l-boolean.lua") loadmodule("l-math.lua") - loadmodule("l-unicode.lua") -- A few slightly higher level support modules: -- cgit v1.2.3