diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/font-ocl.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkiv/font-ocl.lua | 349 |
1 files changed, 176 insertions, 173 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ocl.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ocl.lua index 0976cdb21c0..b17cf991d80 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-ocl.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-ocl.lua @@ -13,20 +13,13 @@ local round, max = math.round, math.round local sortedkeys, sortedhash = table.sortedkeys, table.sortedhash local setmetatableindex = table.setmetatableindex -local formatters = string.formatters -local tounicode = fonts.mappings.tounicode +local formatters = string.formatters +local tounicode = fonts.mappings.tounicode -local helpers = fonts.helpers +local otf = fonts.handlers.otf -local charcommand = helpers.commands.char -local rightcommand = helpers.commands.right -local leftcommand = helpers.commands.left -local downcommand = helpers.commands.down - -local otf = fonts.handlers.otf - -local f_color = formatters["%.3f %.3f %.3f rg"] -local f_gray = formatters["%.3f g"] +local f_color = formatters["%.3f %.3f %.3f rg"] +local f_gray = formatters["%.3f g"] if context then @@ -63,41 +56,31 @@ end) if context then - -- \definefontcolorpalette [emoji-r] [emoji-red,emoji-gray,textcolor] -- looks bad - -- \definefontcolorpalette [emoji-r] [emoji-red,emoji-gray] -- looks okay - local colors = attributes.list[attributes.private('color')] or { } local transparencies = attributes.list[attributes.private('transparency')] or { } function otf.registerpalette(name,values) sharedpalettes[name] = values - local color = lpdf.color - local transparency = lpdf.transparency - local register = colors.register for i=1,#values do local v = values[i] - if v == "textcolor" then - values[i] = false + local c = nil + local t = nil + if type(v) == "table" then + c = colors.register(name,"rgb", + max(round((v.r or 0)*255),255)/255, + max(round((v.g or 0)*255),255)/255, + max(round((v.b or 0)*255),255)/255 + ) else - local c = nil - local t = nil - if type(v) == "table" then - c = register(name,"rgb", - max(round((v.r or 0)*255),255)/255, - max(round((v.g or 0)*255),255)/255, - max(round((v.b or 0)*255),255)/255 - ) - else - c = colors[v] - t = transparencies[v] - end - if c and t then - values[i] = hash[color(1,c) .. " " .. transparency(t)] - elseif c then - values[i] = hash[color(1,c)] - elseif t then - values[i] = hash[color(1,t)] - end + c = colors[v] + t = transparencies[v] + end + if c and t then + values[i] = hash[lpdf.color(1,c) .. " " .. lpdf.transparency(t)] + elseif c then + values[i] = hash[lpdf.color(1,c)] + elseif t then + values[i] = hash[lpdf.color(1,t)] end end end @@ -108,13 +91,11 @@ else -- for generic sharedpalettes[name] = values for i=1,#values do local v = values[i] - if v then - values[i] = hash[f_color( - max(round((v.r or 0)*255),255)/255, - max(round((v.g or 0)*255),255)/255, - max(round((v.b or 0)*255),255)/255 - )] - end + values[i] = hash[f_color( + max(round((v.r or 0)*255),255)/255, + max(round((v.g or 0)*255),255)/255, + max(round((v.b or 0)*255),255)/255 + )] end end @@ -146,11 +127,16 @@ local start = { "pdf", "mode", "font" } -- force text mode (so get q Q right) local push = { "pdf", "page", "q" } local pop = { "pdf", "page", "Q" } +if not LUATEXFUNCTIONALITY or LUATEXFUNCTIONALITY < 6472 then + start = { "nop" } + ----- = stop +end + -- -- This one results in color directives inside BT ET but has less q Q pairs. It -- -- only shows the first glyph in acrobat and nothing more. No problem with other -- -- renderers. -- --- local function initialize(tfmdata,kind,value) -- hm, always value +-- local function initializecolr(tfmdata,kind,value) -- hm, always value -- if value then -- local resources = tfmdata.resources -- local palettes = resources.colorpalettes @@ -175,6 +161,11 @@ local pop = { "pdf", "page", "Q" } -- tfmdata.fonts = { -- { id = 0 } -- } +-- local widths = setmetatableindex(function(t,k) +-- local v = { "right", -k } +-- t[k] = v +-- return v +-- end) -- -- -- local getactualtext = otf.getactualtext -- local default = colorvalues[#colorvalues] @@ -182,6 +173,12 @@ local pop = { "pdf", "page", "Q" } -- local actualb = { "pdf", "page", b } -- saves tables -- local actuale = { "pdf", "page", e } -- saves tables -- -- +-- local cache = setmetatableindex(function(t,k) +-- local v = { "char", k } -- could he a weak shared hash +-- t[k] = v +-- return v +-- end) +-- -- -- for unicode, character in next, characters do -- local description = descriptions[unicode] -- if description then @@ -190,7 +187,7 @@ local pop = { "pdf", "page", "Q" } -- local u = description.unicode or characters[unicode].unicode -- local w = character.width or 0 -- local s = #colorlist --- local goback = w ~= 0 and leftcommand[w] or nil -- needs checking: are widths the same +-- local goback = w ~= 0 and widths[w] or nil -- needs checking: are widths the same -- local t = { -- start, -- not u and actualb or { "pdf", "page", (getactualtext(tounicode(u))) } @@ -205,7 +202,7 @@ local pop = { "pdf", "page", "Q" } -- n = n + 1 t[n] = v -- l = v -- end --- n = n + 1 t[n] = charcommand[entry.slot] +-- n = n + 1 t[n] = cache[entry.slot] -- if s > 1 and i < s and goback then -- n = n + 1 t[n] = goback -- end @@ -224,7 +221,7 @@ local pop = { "pdf", "page", "Q" } -- -- Here we have no color change in BT .. ET and more q Q pairs but even then acrobat -- -- fails displaying the overlays correctly. Other renderers do it right. -local function initialize(tfmdata,kind,value) +local function initializecolr(tfmdata,kind,value) -- hm, always value if value then local resources = tfmdata.resources local palettes = resources.colorpalettes @@ -235,14 +232,8 @@ local function initialize(tfmdata,kind,value) converted = setmetatableindex(convert) resources.converted = converted end - local colorvalues = sharedpalettes[value] - local default = false -- so the text color (bad for icon overloads) - if colorvalues then - default = colorvalues[#colorvalues] - else - colorvalues = converted[palettes[tonumber(value) or 1] or palettes[1]] or { } - end - local classes = #colorvalues + local colorvalues = sharedpalettes[value] or converted[palettes[tonumber(value) or 1] or palettes[1]] or { } + local classes = #colorvalues if classes == 0 then return end @@ -255,12 +246,24 @@ local function initialize(tfmdata,kind,value) tfmdata.fonts = { { id = 0 } } + local widths = setmetatableindex(function(t,k) + local v = { "right", -k } + t[k] = v + return v + end) -- local getactualtext = otf.getactualtext + local default = colorvalues[#colorvalues] local b, e = getactualtext(tounicode(0xFFFD)) local actualb = { "pdf", "page", b } -- saves tables local actuale = { "pdf", "page", e } -- saves tables -- + local cache = setmetatableindex(function(t,k) + local v = { "char", k } -- could he a weak shared hash + t[k] = v + return v + end) + -- for unicode, character in next, characters do local description = descriptions[unicode] if description then @@ -269,7 +272,7 @@ local function initialize(tfmdata,kind,value) local u = description.unicode or characters[unicode].unicode local w = character.width or 0 local s = #colorlist - local goback = w ~= 0 and leftcommand[w] or nil -- needs checking: are widths the same + local goback = w ~= 0 and widths[w] or nil -- needs checking: are widths the same local t = { start, -- really needed not u and actualb or { "pdf", "page", (getactualtext(tounicode(u))) } @@ -288,14 +291,8 @@ local function initialize(tfmdata,kind,value) f = true n = n + 1 t[n] = v l = v - else - if f then - n = n + 1 t[n] = pop - end - f = false - l = nil end - n = n + 1 t[n] = charcommand[entry.slot] + n = n + 1 t[n] = cache[entry.slot] if s > 1 and i < s and goback then n = n + 1 t[n] = goback end @@ -317,60 +314,80 @@ fonts.handlers.otf.features.register { name = "colr", description = "color glyphs", manipulators = { - base = initialize, - node = initialize, + base = initializecolr, + node = initializecolr, } } do + -- local f_setstream = formatters[ [[io.savedata("svg-glyph-%05i",%q)]] ] + -- local f_getstream = formatters[ [[svg-glyph-%05i]] ] + + -- function otfsvg.storepdfdata(pdf) + -- nofstreams = nofstreams + 1 + -- storepdfdata = function(pdf) + -- nofstreams = nofstreams + 1 + -- return f_setstream(nofstreams,pdf), f_getstream(nofstreams) + -- end + -- end + local nofstreams = 0 local f_name = formatters[ [[pdf-glyph-%05i]] ] local f_used = context and formatters[ [[original:///%s]] ] or formatters[ [[%s]] ] local hashed = { } local cache = { } - if epdf then - - local openpdf = epdf.openMemStream - - function otf.storepdfdata(pdf) - local done = hashed[pdf] - if not done then - nofstreams = nofstreams + 1 - local o, n = openpdf(pdf,#pdf,f_name(nofstreams)) - cache[n] = o -- we need to keep in mem - done = f_used(n) - hashed[pdf] = done - end - return done + function otf.storepdfdata(pdf) + local done = hashed[pdf] + if not done then + nofstreams = nofstreams + 1 + local o, n = epdf.openMemStream(pdf,#pdf,f_name(nofstreams)) + cache[n] = o -- we need to keep in mem + done = f_used(n) + hashed[pdf] = done end - - else - - local openpdf = pdfe.new - ----- prefix = "data:application/pdf," - - function otf.storepdfdata(pdf) - local done = hashed[pdf] - if not done then - nofstreams = nofstreams + 1 - local f = f_name(nofstreams) - local n = openpdf(pdf,#pdf,f) - done = f_used(n) - hashed[pdf] = done - end - return done - end - + return nil, done, nil end -end + -- maybe more efficient but much slower (and we hash already) + -- + -- if context then + -- + -- local storepdfdata = otf.storepdfdata + -- local initialized = false + -- + -- function otf.storepdfdata(pdf) + -- if not initialized then + -- if resolvers.setmemstream then + -- local f_setstream = formatters[ [[resolvers.setmemstream("pdf-glyph-%05i",%q,true)]] ] + -- local f_getstream = formatters[ [[memstream:///pdf-glyph-%05i]] ] + -- local f_nilstream = formatters[ [[resolvers.resetmemstream("pdf-glyph-%05i",true)]] ] + -- storepdfdata = function(pdf) + -- local done = hashed[pdf] + -- local set = nil + -- local reset = nil + -- if not done then + -- nofstreams = nofstreams + 1 + -- set = f_setstream(nofstreams,pdf) + -- done = f_getstream(nofstreams) + -- reset = f_nilstream(nofstreams) + -- hashed[pdf] = done + -- end + -- return set, done, reset + -- end + -- otf.storepdfdata = storepdfdata + -- end + -- initialized = true + -- end + -- return storepdfdata(pdf) + -- end + -- + -- end --- I'll probably make a variant for context as we can do it more efficient there than in --- generic. +end -local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = png|svg +local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = sbix|svg if not tfmdata or not pdfshapes or not kind then return end @@ -383,7 +400,7 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = png|svg properties.virtualized = true -- tfmdata.fonts = { - { id = 0 } -- not really needed + { id = 0 } } -- local getactualtext = otf.getactualtext @@ -393,12 +410,6 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = png|svg local actualb = { "pdf", "page", b } -- saves tables local actuale = { "pdf", "page", e } -- saves tables -- - local vfimage = lpdf and lpdf.vfimage or function(wd,ht,dp,data,name) - -- needed for generic (if used there at all) - local name = storepdfdata(data) - return { "image", { filename = name, width = wd, height = ht, depth = dp } } - end - -- for unicode, character in sortedhash(characters) do -- sort is nicer for svg local index = character.index if index then @@ -417,30 +428,31 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = png|svg dy = 0 end if data then - -- We can delay storage by a lua function in commands: but then we need to - -- be able to provide our own mem stream name (so that we can reserve it). - -- Anyway, we will do this different in a future version of context. - local bt = unicode and getactualtext(unicode) - local wd = character.width or 0 - local ht = character.height or 0 - local dp = character.depth or 0 - -- The down and right will change too (we can move that elsewhere). - character.commands = { - not unicode and actualb or { "pdf", "page", (getactualtext(unicode)) }, - downcommand[dp + dy * hfactor], - rightcommand[dx * hfactor], - vfimage(wd,ht,dp,data,name), - actuale, - } - character[kind] = true + local setcode, name, nilcode = storepdfdata(data) + if name then + local bt = unicode and getactualtext(unicode) + local wd = character.width or 0 + local ht = character.height or 0 + local dp = character.depth or 0 + character.commands = { + not unicode and actualb or { "pdf", "page", (getactualtext(unicode)) }, + { "down", dp + dy * hfactor }, + { "right", dx * hfactor }, + -- setcode and { "lua", setcode } or nop, + { "image", { filename = name, width = wd, height = ht, depth = dp } }, + -- nilcode and { "lua", nilcode } or nop, + actuale, + } + character[kind] = true + end end end end end local otfsvg = otf.svg or { } -otf.svg = otfsvg -otf.svgenabled = true +otf.svg = otfsvg +otf.svgenabled = true do @@ -571,27 +583,27 @@ fonts.handlers.otf.features.register { -- This can be done differently e.g. with ffi and gm and we can share code anway. Using -- batchmode in gm is not faster and as it accumulates we would need to flush all --- individual shapes. But ... in context lmtx (and maybe the backport) we will use --- a different and more efficient method anyway. I'm still wondering if I should --- keep color code in generic. Maybe it should be optional. +-- individual shapes. -local otfpng = otf.png or { } -otf.png = otfpng -otf.pngenabled = true +local otfsbix = otf.sbix or { } +otf.sbix = otfsbix +otf.sbixenabled = true do - local report_png = logs.reporter("fonts","png conversion") + -- for now png but also other bitmap formats + + local report_sbix = logs.reporter("fonts","sbix conversion") local loaddata = io.loaddata local savedata = io.savedata local remove = os.remove local runner = sandbox and sandbox.registerrunner { - name = "otfpng", + name = "otfsbix", program = "gm", - template = "convert -quality 100 temp-otf-png-shape.png temp-otf-png-shape.pdf > temp-otf-svg-shape.log", - -- reporter = report_png, + template = "convert -quality 100 temp-otf-sbix-shape.sbix temp-otf-sbix-shape.pdf > temp-otf-svg-shape.log", + -- reporter = report_sbix, } if not runner then @@ -599,29 +611,29 @@ do -- poor mans variant for generic: -- runner = function() - return os.execute("gm convert -quality 100 temp-otf-png-shape.png temp-otf-png-shape.pdf > temp-otf-svg-shape.log") + return os.execute("gm convert -quality 100 temp-otf-sbix-shape.sbix temp-otf-sbix-shape.pdf > temp-otf-svg-shape.log") end end -- Alternatively we can create a single pdf file with -adjoin and then pick up pages from -- that file but creating thousands of small files is no fun either. - function otfpng.topdf(pngshapes) + function otfsbix.topdf(sbixshapes) local pdfshapes = { } - local pngfile = "temp-otf-png-shape.png" - local pdffile = "temp-otf-png-shape.pdf" + local sbixfile = "temp-otf-sbix-shape.sbix" + local pdffile = "temp-otf-sbix-shape.pdf" local nofdone = 0 - local indices = sortedkeys(pngshapes) -- can be sparse + local indices = sortedkeys(sbixshapes) -- can be sparse local nofindices = #indices - report_png("processing %i png containers",nofindices) + report_sbix("processing %i sbix containers",nofindices) statistics.starttiming() for i=1,nofindices do local index = indices[i] - local entry = pngshapes[index] - local data = entry.data -- or placeholder + local entry = sbixshapes[index] + local data = entry.data local x = entry.x local y = entry.y - savedata(pngfile,data) + savedata(sbixfile,data) runner() pdfshapes[index] = { x = x ~= 0 and x or nil, @@ -630,44 +642,43 @@ do } nofdone = nofdone + 1 if nofdone % 100 == 0 then - report_png("%i shapes processed",nofdone) + report_sbix("%i shapes processed",nofdone) end end - report_png("processing %i pdf results",nofindices) - remove(pngfile) + report_sbix("processing %i pdf results",nofindices) + remove(sbixfile) remove(pdffile) statistics.stoptiming() if statistics.elapsedseconds then - report_png("png conversion time %s",statistics.elapsedseconds() or "-") + report_sbix("sbix conversion time %s",statistics.elapsedseconds() or "-") end return pdfshapes + -- end end end --- This will change in a future version of context. More direct. - -local function initializepng(tfmdata,kind,value) -- hm, always value - if value and otf.pngenabled then - local png = tfmdata.properties.png - local hash = png and png.hash - local timestamp = png and png.timestamp +local function initializesbix(tfmdata,kind,value) -- hm, always value + if value and otf.sbixenabled then + local sbix = tfmdata.properties.sbix + local hash = sbix and sbix.hash + local timestamp = sbix and sbix.timestamp if not hash then return end local pdffile = containers.read(otf.pdfcache,hash) local pdfshapes = pdffile and pdffile.pdfshapes if not pdfshapes or pdffile.timestamp ~= timestamp then - local pngfile = containers.read(otf.pngcache,hash) - local pngshapes = pngfile and pngfile.pngshapes - pdfshapes = pngshapes and otfpng.topdf(pngshapes) or { } + local sbixfile = containers.read(otf.sbixcache,hash) + local sbixshapes = sbixfile and sbixfile.sbixshapes + pdfshapes = sbixshapes and otfsbix.topdf(sbixshapes) or { } containers.write(otf.pdfcache, hash, { pdfshapes = pdfshapes, timestamp = timestamp, }) end -- - pdftovirtual(tfmdata,pdfshapes,"png") + pdftovirtual(tfmdata,pdfshapes,"sbix") end end @@ -675,16 +686,8 @@ fonts.handlers.otf.features.register { name = "sbix", description = "sbix glyphs", manipulators = { - base = initializepng, - node = initializepng, + base = initializesbix, + node = initializesbix, } } -fonts.handlers.otf.features.register { - name = "cblc", - description = "cblc glyphs", - manipulators = { - base = initializepng, - node = initializepng, - } -} |