diff options
Diffstat (limited to 'tex')
22 files changed, 604 insertions, 167 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 0de119aa2..d7278d1a4 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{2019.09.29 14:34} +\newcontextversion{2019.10.01 10:36} %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 422ee53a9..25110cc9f 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{2019.09.29 14:34} +\edef\contextversion{2019.10.01 10:36} %D For those who want to use this: diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 0f68e30c3..08c80fddc 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2019.09.29 14:34} +\newcontextversion{2019.10.01 10:36} %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 b255f6bcc..a37681efa 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -45,7 +45,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2019.09.29 14:34} +\edef\contextversion{2019.10.01 10:36} \edef\contextkind {beta} %D Kind of special: diff --git a/tex/context/base/mkiv/context.mkxl b/tex/context/base/mkiv/context.mkxl index 9086b1faf..bd0b8591d 100644 --- a/tex/context/base/mkiv/context.mkxl +++ b/tex/context/base/mkiv/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2019.09.29 14:34} +\edef\contextversion{2019.10.01 10:36} \edef\contextkind {beta} %D Kind of special: diff --git a/tex/context/base/mkiv/font-dsp.lua b/tex/context/base/mkiv/font-dsp.lua index 79749741c..7777f9c6a 100644 --- a/tex/context/base/mkiv/font-dsp.lua +++ b/tex/context/base/mkiv/font-dsp.lua @@ -3159,6 +3159,14 @@ function readers.cpal(f,fontdata,specification) end end +local compress = gzip and gzip.compress +local compressed = compress and gzip.compressed + +-- At some point I will delay loading and only store the offsets (in context lmtx +-- only). + +-- compressed = false + function readers.svg(f,fontdata,specification) local tableoffset = gotodatatable(f,fontdata,"svg",specification.glyphs) if tableoffset then @@ -3184,10 +3192,14 @@ function readers.svg(f,fontdata,specification) for i=1,nofentries do local entry = entries[i] setposition(f,entry.offset) + local data = readstring(f,entry.length) + if compressed and not compressed(data) then + data = compress(data) + end entries[i] = { first = entry.first, last = entry.last, - data = readstring(f,entry.length) + data = data } end fontdata.svgshapes = entries diff --git a/tex/context/base/mkiv/font-imp-dimensions.lua b/tex/context/base/mkiv/font-imp-dimensions.lua index 518d56345..24891a2cd 100644 --- a/tex/context/base/mkiv/font-imp-dimensions.lua +++ b/tex/context/base/mkiv/font-imp-dimensions.lua @@ -48,13 +48,42 @@ local function initialize(tfmdata,key,value) elseif value == "mono" then newwidth = emwidth else + -- there are fonts out there with no x_height ... local spec = settings_to_array(value) - newwidth = tonumber(spec[1]) - newheight = tonumber(spec[2]) - newdepth = tonumber(spec[3]) - if newwidth then newwidth = newwidth * emwidth end - if newheight then newheight = newheight * exheight end - if newdepth then newdepth = newdepth * exheight end + newwidth = spec[1] + newheight = spec[2] + newdepth = spec[3] + local quad = parameters.quad or 0 + local ascender = parameters.ascender or 0 + local descender = parameters.descender or 0 + if newwidth == "max" then + newwidth = quad + else + newwidth = tonumber(newwidth) + if newwidth then + newwidth = newwidth * emwidth + end + end + if newheight == "max" then + newheight = ascender + else + newheight = tonumber(newheight) + if newheight then + newheight = newheight * exheight + end + end + if newdepth == "max" then + newdepth = descender + else + newdepth = tonumber(newdepth) + if newdepth then + newdepth = newdepth * exheight + end + end + if parameters.x_heigth == 0 then + -- maybe a fourth parameter + parameters.x_heigth = (ascender + descender) / 2 + end end if newwidth or newheight or newdepth then for unicode, character in next, characters do diff --git a/tex/context/base/mkiv/font-ogr.lua b/tex/context/base/mkiv/font-ogr.lua index c441ddbf7..a2e5d2e82 100644 --- a/tex/context/base/mkiv/font-ogr.lua +++ b/tex/context/base/mkiv/font-ogr.lua @@ -51,7 +51,7 @@ do return droppedin end - function dropins.provide(method,clone,t_tfmdata,indexdata,...) + function dropins.provide(method,t_tfmdata,indexdata,...) droppedin = dropins.nextid() local t_characters = t_tfmdata.characters local t_descriptions = t_tfmdata.descriptions @@ -59,12 +59,10 @@ do local d_tfmdata = setmetatableindex({ },t_tfmdata) local d_properties = setmetatableindex({ },t_properties) d_tfmdata.properties = d_properties - if clone then - local d_characters = setmetatableindex({ },t_characters) - local d_descriptions = setmetatableindex({ },t_descriptions) - d_tfmdata.characters = d_characters - d_tfmdata.descriptions = d_descriptions - end + local d_characters = setmetatableindex({ },t_characters) + local d_descriptions = setmetatableindex({ },t_descriptions) + d_tfmdata.characters = d_characters + d_tfmdata.descriptions = d_descriptions d_properties.instance = - droppedin -- will become an extra element in the hash t_properties.virtualized = true identifiers[droppedin] = d_tfmdata @@ -75,19 +73,53 @@ do d_properties.indexdata = { indexdata, ... } -- can take quite some memory local slot = #fonts + 1 fonts[slot] = { id = droppedin } - if not clone then - for k, v in next, t_characters do + return slot, droppedin, d_tfmdata, d_properties + end + + function dropins.clone(method,tfmdata,shapes,...) + if method and shapes then + local characters = tfmdata.characters + local descriptions = tfmdata.descriptions + local droppedin, tfmdrop, dropchars, dropdescs, colrshapes + local idx = 255 + local slot = 0 + -- + for k, v in next, characters do local index = v.index - if index and indexdata[index] then - -- todo: use extender - v.commands = { { "slot", slot, k } } + if index then + local description = descriptions[k] + if description then + local shape = shapes[index] + if shape then + if idx >= 255 then + idx = 1 + colrshapes = { filename = shapes.filename, fixdepth = shapes.fixdepth } -- not needed + slot, droppedin, tfmdrop = dropins.provide(method,tfmdata,colrshapes) + dropchars = tfmdrop.characters + dropdescs = tfmdrop.descriptions + else + idx = idx + 1 + end + colrshapes[idx] = shape -- so not: description + -- +-- local helpers = fonts.helpers +-- local prependcommands = helpers.prependcommands +-- print(v.commands) + v.commands = { { "slot", slot, idx } } + -- hack to prevent that type 3 also gets 'use' flags .. todo + local c = { commands = false, index = idx, dropin = tfmdata } + local d = { index = idx, dropin = tfmdata } + setmetatableindex(c,v) + setmetatableindex(d,description) + dropchars[idx] = c + dropdescs[idx] = d + end + end end end else - -- make sure that the drop characters should get a copy with no commands - -- (false will do) + -- error end - return slot, droppedin, d_tfmdata, d_properties end end @@ -198,15 +230,9 @@ do return end -- - -- todo: delay with lua function or plugin in vf handler, saves a lot of - -- overhead - -- local characters = tfmdata.characters local descriptions = tfmdata.descriptions local droppedin, tfmdrop, dropchars, dropdescs, colrshapes - -- alternative 1: - -- local slots = { } - -- alternative 2: local idx = 255 local slot = 0 -- @@ -217,25 +243,10 @@ do if description then local colorlist = description.colors if colorlist then - -- alternative 1: - -- local fnt = div(index,256) - -- local idx = mod(index,256) - -- local slt = slots[fnt] - -- if not slt then - -- colrshapes = { } - -- slot, droppedin, tfmdrop = fonts.dropins.provide("color",true,tfmdata,colrshapes,colorvalues) - -- slt = { slot, colrshapes, tfmdrop.characters, tfmdrop.descriptions } - -- slots[fnt] = slt - -- end - -- slot = slt[1] - -- colrshapes = slt[2] - -- dropchars = slt[3] - -- dropdescs = slt[4] - -- alternative 2: if idx >= 255 then idx = 1 colrshapes = { } - slot, droppedin, tfmdrop = fonts.dropins.provide("color",true,tfmdata,colrshapes,colorvalues) + slot, droppedin, tfmdrop = fonts.dropins.provide("color",tfmdata,colrshapes,colorvalues) dropchars = tfmdrop.characters dropdescs = tfmdrop.descriptions else @@ -290,6 +301,8 @@ do if not hash then return end + local shapes = nil + local method = nil if cached then -- we need a different hash than for mkiv, so we append: local pdfhash = hash .. "-svg" @@ -299,14 +312,14 @@ do if not pdfshapes or pdffile.timestamp ~= timestamp or not next(pdfshapes) or not lfs.isfile(pdftarget) then local svgfile = containers.read(otf.svgcache,hash) local svgshapes = svgfile and svgfile.svgshapes - pdfshapes = svgshapes and metapost.svgshapestopdf(svgshapes,pdftarget,report_svg) or { } + pdfshapes = svgshapes and metapost.svgshapestopdf(svgshapes,pdftarget,report_svg,tfmdata.parameters.units) or { } containers.write(otf.pdfcache, pdfhash, { pdfshapes = pdfshapes, timestamp = timestamp, }) end - -- this can be delayed, no need to keep this in mem - fonts.dropins.provide("pdf",false,tfmdata,pdfshapes) + shapes = pdfshapes + method = "pdf" else local mpsfile = containers.read(otf.mpscache,hash) local mpsshapes = mpsfile and mpsfile.mpsshapes @@ -314,13 +327,18 @@ do local svgfile = containers.read(otf.svgcache,hash) local svgshapes = svgfile and svgfile.svgshapes -- still suboptimal - mpsshapes = svgshapes and metapost.svgshapestomp(svgshapes,report_svg) or { } + mpsshapes = svgshapes and metapost.svgshapestomp(svgshapes,report_svg,tfmdata.parameters.units) or { } containers.write(otf.mpscache, hash, { mpsshapes = mpsshapes, timestamp = timestamp, }) end - fonts.dropins.provide("mps",false,tfmdata,mpsshapes) + shapes = mpsshapes + method = "mps" + end + if shapes then + shapes.fixdepth = value == "fixdepth" + fonts.dropins.clone(method,tfmdata,shapes) end end end @@ -355,7 +373,7 @@ do local pngfile = containers.read(otf.pngcache,hash) local pngshapes = pngfile and pngfile.pngshapes if pngshapes then - fonts.dropins.provide("png",false,tfmdata,pngshapes) + fonts.dropins.clone("png",tfmdata,pngshapes) end end end diff --git a/tex/context/base/mkiv/l-gzip.lua b/tex/context/base/mkiv/l-gzip.lua index 5100e4722..31466bde8 100644 --- a/tex/context/base/mkiv/l-gzip.lua +++ b/tex/context/base/mkiv/l-gzip.lua @@ -5,50 +5,113 @@ if not modules then modules = { } end modules ['l-gzip'] = { license = "see context related readme files" } -if not gzip then +if gzip then - -- no fallback yet + local suffix, suffixes = file.suffix, file.suffixes - return - -end - -local suffix, suffixes = file.suffix, file.suffixes - -function gzip.load(filename) - local f = io.open(filename,"rb") - if not f then - -- invalid file - elseif suffix(filename) == "gz" then - f:close() - local g = gzip.open(filename,"rb") - if g then - local str = g:read("*all") - g:close() + function gzip.load(filename) + local f = io.open(filename,"rb") + if not f then + -- invalid file + elseif suffix(filename) == "gz" then + f:close() + local g = gzip.open(filename,"rb") + if g then + local str = g:read("*all") + g:close() + return str + end + else + local str = f:read("*all") + f:close() return str end - else - local str = f:read("*all") - f:close() - return str end -end -function gzip.save(filename,data) - if suffix(filename) ~= "gz" then - filename = filename .. ".gz" + function gzip.save(filename,data) + if suffix(filename) ~= "gz" then + filename = filename .. ".gz" + end + local f = io.open(filename,"wb") + if f then + local s = zlib.compress(data or "",9,nil,15+16) + f:write(s) + f:close() + return #s + end end - local f = io.open(filename,"wb") - if f then - local s = zlib.compress(data or "",9,nil,15+16) - f:write(s) - f:close() - return #s + + function gzip.suffix(filename) + local suffix, extra = suffixes(filename) + local gzipped = extra == "gz" + return suffix, gzipped end + +else + + -- todo: fallback on flate + end -function gzip.suffix(filename) - local suffix, extra = suffixes(filename) - local gzipped = extra == "gz" - return suffix, gzipped +if flate then + + local type = type + local find = string.find + + local compress = flate.gz_compress + local decompress = flate.gz_decompress + + local absmax = 128*1024*1024 + local initial = 64*1024 + local identifier = "^\x1F\x8B\x08" + + function gzip.compressed(s) + return s and find(s,identifier) + end + + function gzip.compress(s,level) + if s and not find(s,identifier) then -- the find check might go away + if not level then + level = 3 + elseif level <= 0 then + return s + elseif level > 9 then + level = 9 + end + return compress(s,level) or s + end + end + + function gzip.decompress(s,size,iterate) + if s and find(s,identifier) then + if type(size) ~= "number" then + size = initial + end + if size > absmax then + size = absmax + end + if type(iterate) == "number" then + max = size * iterate + elseif iterate == nil or iterate == true then + iterate = true + max = absmax + end + if max > absmax then + max = absmax + end + while true do + local d = decompress(s,size) + if d then + return d + end + size = 2 * size + if not iterate or size > max then + return false + end + end + else + return s + end + end + end diff --git a/tex/context/base/mkiv/l-lpeg.lua b/tex/context/base/mkiv/l-lpeg.lua index 51bc1d3df..7979a40fb 100644 --- a/tex/context/base/mkiv/l-lpeg.lua +++ b/tex/context/base/mkiv/l-lpeg.lua @@ -295,7 +295,7 @@ patterns.longtostring = Cs(whitespace^0/"" * ((patterns.quoted + nonwhitespace^ -- return P { P(pattern) + 1 * V(1) } -- end -function anywhere(pattern) -- faster +local function anywhere(pattern) -- faster return (1-P(pattern))^0 * P(pattern) end diff --git a/tex/context/base/mkiv/lpdf-emb.lua b/tex/context/base/mkiv/lpdf-emb.lua index 1cdcac1ae..0447ce9b0 100644 --- a/tex/context/base/mkiv/lpdf-emb.lua +++ b/tex/context/base/mkiv/lpdf-emb.lua @@ -1525,12 +1525,14 @@ do local embedimage = images.embed - local f_glyph = formatters["G%d"] - local f_char = formatters["BT /V%d 1 Tf [<%04X>] TJ ET"] - local f_width = formatters["%.6N 0 d0"] - local f_index = formatters["I%d"] - local f_image = formatters["%.6N 0 d0 /%s Do"] - local f_stream = formatters["%.6N 0 d0 %s"] + local f_glyph = formatters["G%d"] + local f_char = formatters["BT /V%d 1 Tf [<%04X>] TJ ET"] + local f_width = formatters["%.6N 0 d0"] + local f_index = formatters["I%d"] + local f_image = formatters["%.6N 0 d0 /%s Do"] + local f_image_d = formatters["%.6N 0 d0 1 0 0 1 0 %.3N cm /%s Do"] + local f_stream = formatters["%.6N 0 d0 %s"] + local f_stream_d = formatters["%.6N 0 d0 1 0 0 1 0 %.3N cm %s"] -- A type 3 font has at most 256 characters and Acrobat also wants a zero slot -- to be filled. We can share a mandate zero slot character. @@ -1558,6 +1560,9 @@ do return result.glyphs, widthfactor / 65536, scalefactor, readers.pktopdf end + -- not scaling in svg but here using a cm might be more efficient in terms of bytes + -- as we get smaller numbers + -- pdf inclusion function methods.pdf(filename,details) @@ -1567,15 +1572,25 @@ do local xforms = pdfdictionary() local nofglyphs = 0 if pdfdoc then + local scale = 10 * details.parameters.size/details.parameters.designsize + local units = details.parameters.units + local factor = units * bpfactor / scale + local fixdepth = pdfshapes.fixdepth local function pdftopdf(glyph,width,data) local image = copypage(pdfdoc,glyph) - width = 100 * width * bpfactor embedimage(image) + width = width * factor nofglyphs = nofglyphs + 1 local name = f_glyph(nofglyphs) xforms[name] = pdfreference(image.objnum) - local pdf = f_image(width,name) - return pdf, width + if fixdepth then + local depth = data.depth or 0 + local height = data.height or 0 + if depth ~= 0 or height ~= 0 then + return f_stream_d(width,(-height-depth)*factor,pdf), width + end + end + return f_image(width,name), width end local function closepdf() -- closepdf(pdfdoc) @@ -1583,27 +1598,44 @@ do local function getresources() return pdfdictionary { XObject = xforms } end - return pdfshapes, 1, 0.001, pdftopdf, closepdf, getresources + return pdfshapes, 1, 1/units, pdftopdf, closepdf, getresources end end -- mps inclusion + local decompress = gzip.decompress + function methods.mps(filename,details) local properties = details.properties local mpshapes = properties.indexdata[1] - local function mpstopdf(mp,width,data) - local pdf = metapost.simple("metafun",mp,true) -- can be sped up, minifun - local width = 100 * width * bpfactor - local stream = f_stream(width,pdf) - return stream, width - end - local function getresources() - return lpdf.collectedresources { - serialize = false, - } + if mpshapes then + local scale = 10 * details.parameters.size/details.parameters.designsize + local units = details.parameters.units + local factor = units * bpfactor / scale + local fixdepth = mpshapes.fixdepth + local function mpstopdf(mp,width,data) + if decompress then + mp = decompress(mp) + end + local pdf = metapost.simple("metafun",mp,true) -- can be sped up, minifun + local width = width * factor + if fixdepth then + local depth = data.depth or 0 + local height = data.height or 0 + if depth ~= 0 or height ~= 0 then + return f_stream_d(width,(-height-depth)*factor,pdf), width + end + end + return f_stream(width,pdf), width + end + local function getresources() + return lpdf.collectedresources { + serialize = false, + } + end + return mpshapes, 1, 1/units, mpstopdf, nil, getresources end - return mpshapes, 1, 0.001, mpstopdf, nil, getresources end -- png inclusion @@ -1625,13 +1657,8 @@ do local function pngtopdf(glyph,width,data) local info = graphics.identifiers.png(glyph.data,"string") local image = lpdf.injectors.png(info,"string") - local bbox = image.bbox - local llx = bbox[1] * bpfactor - local lly = bbox[2] * bpfactor - local urx = bbox[3] * bpfactor - local ury = bbox[4] * bpfactor - width = width * bpfactor / 10 embedimage(image) + width = width * bpfactor / 10 nofglyphs = nofglyphs + 1 local name = f_glyph(nofglyphs) xforms[name] = pdfreference(image.objnum) @@ -1659,7 +1686,7 @@ do if colorlist then local dropdata = data.dropin local dropid = dropdata.properties.id - local dropunits = dropdata.parameters.units + local dropunits = dropdata.parameters.units -- shared usedfonts[dropid] = dropid local w = description.width or 0 @@ -1668,7 +1695,6 @@ do local t = { f_width(w) } local n = 1 local d = colrvalues[#colrvalues] - for i=1,s do local entry = colorlist[i] local v = colrvalues[entry.class] or d @@ -1740,7 +1766,6 @@ do for i=1,maxindex-minindex+1 do widths[i] = 0 end - for index, data in sortedhash(indices) do local name = f_index(index) local glyph = glyphs[index] @@ -1773,7 +1798,11 @@ do Differences = differences, } local tounicode = tounicodedictionary(details,indices,maxindex,basefontname) - local resources = getresources and getresources() or lpdf.procset(true) + local resources = getresources and getresources() + if not resources or not next(resources) then + -- resources = lpdf.procset(true) + resources = nil + end local descriptor = pdfdictionary { -- most is optional in type3 Type = pdfconstant("FontDescriptor"), @@ -1794,7 +1823,7 @@ do Widths = pdfreference(pdfflushobject(widths)), FontDescriptor = pdfreference(pdfflushobject(descriptor)), Resources = resources, - ToUnicode = pdfreference(pdfflushstreamobject(tounicode)), + ToUnicode = tounicode and pdfreference(pdfflushstreamobject(tounicode)), } pdfflushobject(object,parent) if reset then diff --git a/tex/context/base/mkiv/lxml-tab.lua b/tex/context/base/mkiv/lxml-tab.lua index 3ade1c92b..8f6379f2f 100644 --- a/tex/context/base/mkiv/lxml-tab.lua +++ b/tex/context/base/mkiv/lxml-tab.lua @@ -1160,13 +1160,15 @@ publicentityfile + end -grammar_parsed_text_one_nop , -grammar_parsed_text_two_nop , -grammar_unparsed_text_nop = install(space, spacing, anything) - -grammar_parsed_text_one_yes , -grammar_parsed_text_two_yes , -grammar_unparsed_text_yes = install(space_nl, spacing_nl, anything_nl) +local + grammar_parsed_text_one_nop , + grammar_parsed_text_two_nop , + grammar_unparsed_text_nop = install(space, spacing, anything) + +local + grammar_parsed_text_one_yes , + grammar_parsed_text_two_yes , + grammar_unparsed_text_yes = install(space_nl, spacing_nl, anything_nl) -- maybe we will add settings to result as well diff --git a/tex/context/base/mkiv/mlib-ctx.mkiv b/tex/context/base/mkiv/mlib-ctx.mkiv index 860cb688c..a1ed7efeb 100644 --- a/tex/context/base/mkiv/mlib-ctx.mkiv +++ b/tex/context/base/mkiv/mlib-ctx.mkiv @@ -20,7 +20,7 @@ \registerctxluafile{mlib-int}{} \doifelsefileexists{mlib-cnt.lua}{\registerctxluafile{mlib-cnt}{optimize}}{} -\doifelsefileexists{mlib-svg.lua}{\registerctxluafile{mlib-svg}{}}{} +\doifelsefileexists{mlib-svg.lua}{\registerctxluafile{mlib-svg}{optimize}}{} \unprotect diff --git a/tex/context/base/mkiv/mlib-lmp.lua b/tex/context/base/mkiv/mlib-lmp.lua index 22607be8d..dc130c2fd 100644 --- a/tex/context/base/mkiv/mlib-lmp.lua +++ b/tex/context/base/mkiv/mlib-lmp.lua @@ -6,10 +6,11 @@ if not modules then modules = { } end modules ['mlib-lmp'] = { license = "see context related readme files", } -local aux = mp.aux -local mpnumeric = aux.numeric -local mppair = aux.pair -local mpquoted = aux.quoted +local aux = mp.aux +local mpnumeric = aux.numeric +local mppair = aux.pair +local mpquoted = aux.quoted +local mpdirect = aux.direct -- todo: use a stack? @@ -136,9 +137,20 @@ do end function mp.lmt_svg_include() - local name = metapost.getparameter { "svg", "filename" } - local mps = metapost.svgtomp { - data = name and name ~= "" and io.loaddata(name) or "", - } - mp.direct(mps) + local filename = metapost.getparameter { "filename" } + local fontname = metapost.getparameter { "fontname" } + local metacode = nil + if fontname and fontname ~= "" then + local unicode = metapost.getparameter { "unicode" } + if unicode then + metacode = metapost.svgglyphtomp(fontname,math.round(unicode)) + end + elseif filename and filename ~= "" then + metacode = metapost.svgtomp { + data = io.loaddata(filename) + } + end + if metacode then + mpdirect(metacode) + end end diff --git a/tex/context/base/mkiv/mlib-svg.lua b/tex/context/base/mkiv/mlib-svg.lua index c3635480d..d9156d2e8 100644 --- a/tex/context/base/mkiv/mlib-svg.lua +++ b/tex/context/base/mkiv/mlib-svg.lua @@ -16,22 +16,25 @@ if not modules then modules = { } end modules ['mlib-svg'] = { -- Written with Anne Clark on speakers as distraction. --- TODO: - +-- Todo when I run into an example: +-- +-- var(color,color) +-- --color<decimal> +-- currentColor : when i run into an example +-- some more fonts +-- +-- Todo: some day +-- -- optimize --- test for gzip header 0x1F 0x8B 0x08 --- var() --- color hash --- currentColor -- instances --- --color<decimal> --- glyph<id> +-- withpen -> pickup +-- +-- Todo: when i am motivated +-- -- shading -- "none" -> false -- clip = [ auto | rect(llx,lly,urx,ury) ] (in svg) -- xlink url ... whatever --- mp svg module + shortcuts --- withpen -> pickup -- The fact that in the more recent versions of SVG the older text related elements -- are depricated and not even supposed to be supported, combined with the fact that @@ -54,6 +57,7 @@ local pi, sin, cos, asin, sind, cosd, tan, abs, sqrt = math.pi, math.sin, math.c local concat, setmetatableindex = table.concat, table.setmetatableindex local gmatch, gsub, find, match, rep = string.gmatch, string.gsub, string.find, string.match, string.rep local formatters = string.formatters +local extract = bit32.extract local xmlconvert, xmlcollected, xmlcount, xmlfirst, xmlroot, xmltext = xml.convert, xml.collected, xml.count, xml.first, xml.root, xml.text @@ -138,6 +142,13 @@ local f_transform_stop = formatters[") %s ;"] local s_offset_start = "draw image ( " local f_offset_stop = formatters[") shifted (%.3N,%.3N) ;"] +local s_scaled_start = "draw image ( " +local f_scaled_stop = formatters[") scaled %.3N ;"] + +local s_hacked_start = "draw image (" +local f_hacked_stop = formatters[") shifted (0,%.3N) scaled %.3N ;"] +-- local f_hacked_stop = formatters[") scaled %.3N ;"] + local f_viewport_start = "draw image (" local f_viewport_stop = ") ;" local f_viewport_shift = formatters["currentpicture := currentpicture shifted (%03N,%03N);"] @@ -161,6 +172,171 @@ local f_shade_two = formatters['withprescript "sh_center_b=%.3N %.3N"'] local f_text_scaled = formatters['(textext.drt("%s") scaled %.3N shifted (%.3N,%.3N))'] local f_text_normal = formatters['(textext.drt("%s") shifted (%.3N,%.3N))'] +-- We can actually use the svg color definitions from the tex end but maybe a user doesn't +-- want those replace the normal definitions. + +local svgcolors = { + black = 0x000000, + navy = 0x000080, + darkblue = 0x00008B, + mediumblue = 0x0000CD, + blue = 0x0000FF, + darkgreen = 0x006400, + green = 0x008000, + teal = 0x008080, + darkcyan = 0x008B8B, + deepskyblue = 0x00BFFF, + darkturquoise = 0x00CED1, + mediumspringgreen = 0x00FA9A, + lime = 0x00FF00, + springgreen = 0x00FF7F, + cyan = 0x00FFFF, + aqua = 0x00FFFF, + midnightblue = 0x191970, + dodgerblue = 0x1E90FF, + lightseagreen = 0x20B2AA, + forestgreen = 0x228B22, + seagreen = 0x2E8B57, + darkslategray = 0x2F4F4F, + darkslategrey = 0x2F4F4F, + limegreen = 0x32CD32, + mediumseagreen = 0x3CB371, + turquoise = 0x40E0D0, + royalblue = 0x4169E1, + steelblue = 0x4682B4, + darkslateblue = 0x483D8B, + mediumturquoise = 0x48D1CC, + indigo = 0x4B0082, + darkolivegreen = 0x556B2F, + cadetblue = 0x5F9EA0, + cornflowerblue = 0x6495ED, + mediumaquamarine = 0x66CDAA, + dimgrey = 0x696969, + dimgray = 0x696969, + slateblue = 0x6A5ACD, + olivedrab = 0x6B8E23, + slategrey = 0x708090, + slategray = 0x708090, + lightslategray = 0x778899, + lightslategrey = 0x778899, + mediumslateblue = 0x7B68EE, + lawngreen = 0x7CFC00, + chartreuse = 0x7FFF00, + aquamarine = 0x7FFFD4, + maroon = 0x800000, + purple = 0x800080, + olive = 0x808000, + gray = 0x808080, + grey = 0x808080, + skyblue = 0x87CEEB, + lightskyblue = 0x87CEFA, + blueviolet = 0x8A2BE2, + darkred = 0x8B0000, + darkmagenta = 0x8B008B, + saddlebrown = 0x8B4513, + darkseagreen = 0x8FBC8F, + lightgreen = 0x90EE90, + mediumpurple = 0x9370DB, + darkviolet = 0x9400D3, + palegreen = 0x98FB98, + darkorchid = 0x9932CC, + yellowgreen = 0x9ACD32, + sienna = 0xA0522D, + brown = 0xA52A2A, + darkgray = 0xA9A9A9, + darkgrey = 0xA9A9A9, + lightblue = 0xADD8E6, + greenyellow = 0xADFF2F, + paleturquoise = 0xAFEEEE, + lightsteelblue = 0xB0C4DE, + powderblue = 0xB0E0E6, + firebrick = 0xB22222, + darkgoldenrod = 0xB8860B, + mediumorchid = 0xBA55D3, + rosybrown = 0xBC8F8F, + darkkhaki = 0xBDB76B, + silver = 0xC0C0C0, + mediumvioletred = 0xC71585, + indianred = 0xCD5C5C, + peru = 0xCD853F, + chocolate = 0xD2691E, + tan = 0xD2B48C, + lightgray = 0xD3D3D3, + lightgrey = 0xD3D3D3, + thistle = 0xD8BFD8, + orchid = 0xDA70D6, + goldenrod = 0xDAA520, + palevioletred = 0xDB7093, + crimson = 0xDC143C, + gainsboro = 0xDCDCDC, + plum = 0xDDA0DD, + burlywood = 0xDEB887, + lightcyan = 0xE0FFFF, + lavender = 0xE6E6FA, + darksalmon = 0xE9967A, + violet = 0xEE82EE, + palegoldenrod = 0xEEE8AA, + lightcoral = 0xF08080, + khaki = 0xF0E68C, + aliceblue = 0xF0F8FF, + honeydew = 0xF0FFF0, + azure = 0xF0FFFF, + sandybrown = 0xF4A460, + wheat = 0xF5DEB3, + beige = 0xF5F5DC, + whitesmoke = 0xF5F5F5, + mintcream = 0xF5FFFA, + ghostwhite = 0xF8F8FF, + salmon = 0xFA8072, + antiquewhite = 0xFAEBD7, + linen = 0xFAF0E6, + lightgoldenrodyellow = 0xFAFAD2, + oldlace = 0xFDF5E6, + red = 0xFF0000, + fuchsia = 0xFF00FF, + magenta = 0xFF00FF, + deeppink = 0xFF1493, + orangered = 0xFF4500, + tomato = 0xFF6347, + hotpink = 0xFF69B4, + coral = 0xFF7F50, + darkorange = 0xFF8C00, + lightsalmon = 0xFFA07A, + orange = 0xFFA500, + lightpink = 0xFFB6C1, + pink = 0xFFC0CB, + gold = 0xFFD700, + peachpuff = 0xFFDAB9, + navajowhite = 0xFFDEAD, + moccasin = 0xFFE4B5, + bisque = 0xFFE4C4, + mistyrose = 0xFFE4E1, + blanchedalmond = 0xFFEBCD, + papayawhip = 0xFFEFD5, + lavenderblush = 0xFFF0F5, + seashell = 0xFFF5EE, + cornsilk = 0xFFF8DC, + lemonchiffon = 0xFFFACD, + floralwhite = 0xFFFAF0, + snow = 0xFFFAFA, + yellow = 0xFFFF00, + lightyellow = 0xFFFFE0, + ivory = 0xFFFFF0, + white = 0xFFFFFF, +} + +local svgcolor = setmetatableindex(function(t,k) + -- we delay building all these strings + local v = svgcolors[k] + if v then + v = f_rgb(extract(v,16,8),extract(v,8,8),extract(v,0,8)) + else + v = false + end + t[k] = v + return v +end) + local p_digit = lpegpatterns.digit local p_hexdigit = lpegpatterns.hexdigit local p_space = lpegpatterns.whitespace @@ -627,7 +803,8 @@ local function grabpath(str) prev = "C" goto continue ::close:: - n = n + 1 ; t[n] = prev == "C" and "..cycle" or "--cycle" + -- n = n + 1 ; t[n] = prev == "C" and "..cycle" or "--cycle" + n = n + 1 ; t[n] = "--cycle" if n > 0 then a = a + 1 ; all[a] = concat(t,"",1,n) ; n = 0 end @@ -915,7 +1092,7 @@ do local colorb = a["stop-color"] local opacity = a["stop-opacity"] - colorb = colorb and hexcolor3(colorb) or colorb + colorb = colorb and (hexcolor3(colorb) or svgcolor[colorb] or colorb) colora = colora or colorb -- what if no percentage @@ -959,7 +1136,7 @@ do if not c then c = rgbacolor(stroke) if not c then - c = f_color(stroke) + c = f_color(svgcolor[stroke] or stroke) end end local o = a["stroke-opacity"] or a.opacity @@ -981,7 +1158,7 @@ do if not c then c = hexcolor(fill) if not c then - c = f_color(fill) + c = f_color(svgcolor[fill] or fill) end end local o = a["fill-opacity"] or a.opacity @@ -1018,7 +1195,9 @@ do local function viewport(x,y,w,h,noclip) r = r + 1 ; result[r] = f_viewport_start return function() - r = r + 1 ; result[r] = f_viewport_shift(-x,y) + if x ~= 0 or y ~= 0 then + r = r + 1 ; result[r] = f_viewport_shift(-x,y) + end if not noclip then r = r + 1 ; result[r] = f_viewport_clip(w,-h) end @@ -1372,14 +1551,22 @@ do r = r + 1 ; result[r] = text end - function handlers.svg(c,top,x,y,w,h,noclip) + function handlers.svg(c,top,x,y,w,h,noclip,notransform,normalize) local a = setmetatableindex(c.at,top) local v = a.viewBox local t = a.transform local wrapupoffset local wrapupviewport + local btransform + local etransform + local bhacked + local ehacked + local wd = w -- local ex, em local xpct, ypct, rpct + if notransform then +-- t = nil + end if trace then report("view: %s, xpct %.3N, ypct %.3N","before",percentage_x,percentage_y) end @@ -1411,14 +1598,25 @@ do if t then btransform, etransform = transform(t,true) end + -- some fonts need this (bad transforms + viewbox) + if v and normalize and w and wd and w ~= wd and w > 0 and wd > 0 then + bhacked = s_hacked_start + ehacked = f_hacked_stop(y or 0,wd/w) + end if btransform then r = r + 1 ; result[r] = btransform end + if bhacked then + r = r + 1 ; result[r] = bhacked + end wrapupoffset = offset(a) process(c,"/*",top or defaults) if wrapupoffset then wrapupoffset() end + if ehacked then + r = r + 1 ; result[r] = ehacked + end if etransform then r = r + 1 ; result[r] = etransform end @@ -1448,7 +1646,7 @@ do end end - function metapost.svgtomp(specification,pattern) + function metapost.svgtomp(specification,pattern,notransform,normalize) local mps = "" local svg = specification.data if type(svg) == "string" then @@ -1464,9 +1662,11 @@ do nil, specification.x, specification.y, - specification.w, - specification.h, - specification.noclip + specification.width, + specification.height, + specification.noclip, + notransform, + normalize ) mps = concat(result," ") root, result, r, definitions, styles, bodyfont = false, false, false, false, false, false @@ -1481,6 +1681,8 @@ do end +-- These helpers might move to their own module .. some day ... + function metapost.showsvgpage(data) local dd = data.data if type(dd) == "table" then @@ -1533,6 +1735,9 @@ do -- cache. This is the old method updated. Maybe a future version will just do this runtime -- but for now this is the most efficient method. + local decompress = gzip.decompress + local compress = gzip.compress + function metapost.svgshapestopdf(svgshapes,pdftarget,report_svg) local texname = "temp-otf-svg-to-pdf.tex" local pdfname = "temp-otf-svg-to-pdf.pdf" @@ -1566,6 +1771,9 @@ do for i=1,nofshapes do local entry = svgshapes[i] local data = entry.data + if decompress then + data = decompress(data,128*1024) or data + end local specification = { data = xmlconvert(data), x = 0, @@ -1580,7 +1788,7 @@ do pdfpages[index] = pdfpage local pattern = "/svg[@id='glyph" .. index .. "']" n = n + 1 ; t[n] = "\\startMPpage" - n = n + 1 ; t[n] = metapost.svgtomp(specification,pattern) or "" + n = n + 1 ; t[n] = metapost.svgtomp(specification,pattern,true,true) or "" n = n + 1 ; t[n] = "\\stopMPpage" end end @@ -1610,6 +1818,9 @@ do for i=1,nofshapes do local entry = svgshapes[i] local data = entry.data + if decompress then + data = decompress(data,128*1024) or data + end local specification = { data = xmlconvert(data), x = 0, @@ -1621,7 +1832,11 @@ do for index=entry.first,entry.last do if not mpshapes[index] then local pattern = "/svg[@id='glyph" .. index .. "']" - mpshapes[index] = metapost.svgtomp(specification,pattern) or "" + local mpcode = metapost.svgtomp(specification,pattern,true,true) or "" + if mpcode ~= "" and compress then + mpcode = compress(mpcode) or mpcode + end + mpshapes[index] = mpcode end end end @@ -1632,4 +1847,54 @@ do return mpshapes end + function metapost.svgglyphtomp(fontname,unicode) + if fontname and unicode then + local id = fonts.definers.internal { name = fontname } + if id then + local tfmdata = fonts.hashes.identifiers[id] + if tfmdata then + local properties = tfmdata.properties + local svg = properties.svg + local hash = svg and svg.hash + local timestamp = svg and svg.timestamp + if hash then + local svgfile = containers.read(fonts.handlers.otf.svgcache,hash) + local svgshapes = svgfile and svgfile.svgshapes + if svgshapes then + if type(unicode) == "string" then + unicode = utf.byte(unicode) + end + local chardata = tfmdata.characters[unicode] + local index = chardata and chardata.index + if index then + for i=1,#svgshapes do + local entry = svgshapes[i] + if index >= entry.first and index <= entry.last then + local data = entry.data + if data then + local root = xml.convert(gzip.decompress(data,128*1024) or data) + return metapost.svgtomp ( + { + data = root, + x = 0, + y = 1000, + width = 1000, + height = 1000, + noclip = true, + }, + "/svg[@id='glyph" .. index .. "']", + true, + true + ) + end + end + end + end + end + end + end + end + end + end + end diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex 13226aea6..9298a31e7 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex 71314c8ea..6f7d7e6b5 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/trac-set.lua b/tex/context/base/mkiv/trac-set.lua index 4a22282a8..d43fd6d0d 100644 --- a/tex/context/base/mkiv/trac-set.lua +++ b/tex/context/base/mkiv/trac-set.lua @@ -30,11 +30,11 @@ local data = { } -- The sorting is needed to get a predictable setters in case of *. local trace_initialize = false -- only for testing during development +local frozen = true -- this needs checking function setters.initialize(filename,name,values) -- filename only for diagnostics local setter = data[name] if setter then - frozen = true -- don't permitoverload -- trace_initialize = true local data = setter.data if data then diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf Binary files differindex f76346da3..8aeaeaf09 100644 --- a/tex/context/interface/mkiv/i-context.pdf +++ b/tex/context/interface/mkiv/i-context.pdf diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf Binary files differindex ceb80af79..66f97e2ec 100644 --- a/tex/context/interface/mkiv/i-readme.pdf +++ b/tex/context/interface/mkiv/i-readme.pdf diff --git a/tex/context/modules/common/s-abbreviations-logos.tex b/tex/context/modules/common/s-abbreviations-logos.tex index c124a3a94..9cf7085f5 100644 --- a/tex/context/modules/common/s-abbreviations-logos.tex +++ b/tex/context/modules/common/s-abbreviations-logos.tex @@ -313,6 +313,7 @@ \logo [TUGBOAT] {Tug\-Boat} \logo [TUGNEWS] {Tug\-News} \logo [TYPEONE] {Type1} +\logo [TYPETHREE] {Type3} \logo [UCS] {ucs} \logo [UNICODE] {Uni\-code} \logo [UNIX] {Unix} diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index d9de24400..f23352419 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 : 09/29/19 14:34:09 +-- merge date : 10/01/19 10:36:53 do -- begin closure to overcome local limits and interference @@ -296,7 +296,7 @@ patterns.propername=(uppercase+lowercase+underscore)*(uppercase+lowercase+unders patterns.somecontent=(anything-newline-space)^1 patterns.beginline=#(1-newline) patterns.longtostring=Cs(whitespace^0/""*((patterns.quoted+nonwhitespace^1+whitespace^1/""*(endofstring+Cc(" ")))^0)) -function anywhere(pattern) +local function anywhere(pattern) return (1-P(pattern))^0*P(pattern) end lpeg.anywhere=anywhere @@ -19800,6 +19800,8 @@ function readers.cpal(f,fontdata,specification) fontdata.colorpalettes=palettes end end +local compress=gzip and gzip.compress +local compressed=compress and gzip.compressed function readers.svg(f,fontdata,specification) local tableoffset=gotodatatable(f,fontdata,"svg",specification.glyphs) if tableoffset then @@ -19821,10 +19823,14 @@ function readers.svg(f,fontdata,specification) for i=1,nofentries do local entry=entries[i] setposition(f,entry.offset) + local data=readstring(f,entry.length) + if compressed and not compressed(data) then + data=compress(data) + end entries[i]={ first=entry.first, last=entry.last, - data=readstring(f,entry.length) + data=data } end fontdata.svgshapes=entries |