diff options
author | Hans Hagen <pragma@wxs.nl> | 2020-07-20 11:09:33 +0200 |
---|---|---|
committer | Context Git Mirror Bot <phg@phi-gamma.net> | 2020-07-20 11:09:33 +0200 |
commit | 81095dd1bf20eb5f7e126adbdc8047f940504180 (patch) | |
tree | c0cdf7b074e8a2d00c56fde09519e89f155bd425 /tex/context/base/mkiv/font-ogr.lua | |
parent | f1129626606384a7a55a21a83531f51f8b5dee25 (diff) | |
download | context-81095dd1bf20eb5f7e126adbdc8047f940504180.tar.gz |
2020-07-20 10:42:00
Diffstat (limited to 'tex/context/base/mkiv/font-ogr.lua')
-rw-r--r-- | tex/context/base/mkiv/font-ogr.lua | 672 |
1 files changed, 0 insertions, 672 deletions
diff --git a/tex/context/base/mkiv/font-ogr.lua b/tex/context/base/mkiv/font-ogr.lua deleted file mode 100644 index 94cf91494..000000000 --- a/tex/context/base/mkiv/font-ogr.lua +++ /dev/null @@ -1,672 +0,0 @@ -if not modules then modules = { } end modules ['font-ogr'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- Here we deal with graphic variants and for now also color support ends up here --- but that might change. It's lmtx only code. - -if not context then - return -elseif CONTEXTLMTXMODE == 0 then - return -end - -local tostring, tonumber, next, type = tostring, tonumber, next, type -local round, max, mod, div = math.round, math.max, math.mod, math.div -local find = string.find -local concat, setmetatableindex, sortedhash = table.concat, table.setmetatableindex, table.sortedhash -local utfbyte = utf.byte -local formatters = string.formatters -local settings_to_hash_strict, settings_to_array = utilities.parsers.settings_to_hash_strict, utilities.parsers.settings_to_array - -local otf = fonts.handlers.otf -local otfregister = otf.features.register -otf.svgenabled = true -otf.pngenabled = true - --- Just to remind me ... rewritten around the time this was posted on YT which --- was also around the 2019 ctx meeting: --- --- Gavin Harrison - "Threatening War" by The Pineapple Thief --- https://www.youtube.com/watch?v=ENF9wth4kwM - --- todo: svg color plugin --- todo: get rid of double cm in svg (tricky as also elsewhere) --- todo: png offsets (depth) --- todo: maybe collapse indices so that we have less files (harder to debug) --- todo: manage (read: assign) font id's in lua so we know in advance - --- what here and what in backend ... - -do - - -- This is a prelude to something better but I'm still experimenting. - - local dropins = { } - fonts.dropins = dropins - local droppedin = 0 - local identifiers = fonts.hashes.identifiers - - function dropins.nextid() - droppedin = droppedin - 1 - return droppedin - end - - -- todo: pass specification table instead - - function dropins.provide(method,t_tfmdata,indexdata,...) - local droppedin = dropins.nextid() - local t_characters = t_tfmdata.characters - local t_descriptions = t_tfmdata.descriptions - local t_properties = t_tfmdata.properties - local d_tfmdata = setmetatableindex({ },t_tfmdata) - local d_properties = setmetatableindex({ },t_properties) - d_tfmdata.properties = d_properties - local d_characters = { } -- setmetatableindex({ },t_characters) -- hm, index vs unicode - local d_descriptions = { } -- setmetatableindex({ },t_descriptions) -- hm, index vs unicode - 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 - local fonts = t_tfmdata.fonts or { } - t_tfmdata.fonts = fonts - d_properties.format = "type3" - d_properties.method = method - d_properties.indexdata = { indexdata, ... } -- can take quite some memory - local slot = #fonts + 1 - fonts[slot] = { id = droppedin } - return slot, droppedin, d_tfmdata, d_properties - end - - -- todo: delay this, in which case we can be leaner and meaner - - function dropins.clone(method,tfmdata,shapes,...) -- by index - 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 then - local description = descriptions[k] - if description then - local shape = shapes[index] - if shape then - if idx >= 255 then - idx = 1 - colrshapes = setmetatableindex({ },shapes) - 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 - -- todo: prepend - v.commands = { { "slot", slot, idx } } - -- hack to prevent that type 3 also gets 'use' flags .. todo - local c = { commands = false, index = idx, dropin = tfmdrop } - local d = { } -- { index = idx, dropin = tfmdrop } - setmetatableindex(c,v) - setmetatableindex(d,description) - dropchars[idx] = c - dropdescs[idx] = d -- not needed - end - end - end - end - else - -- error - end - end - - function dropins.swap(method,tfmdata,shapes,...) -- by unicode - 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 - -- we can have a variant where shaped are by unicode and not by index - for k, v in next, characters do - local description = descriptions[k] - if description then - local shape = shapes[k] - if shape then - if idx >= 255 then - idx = 1 - colrshapes = setmetatableindex({ },shapes) - 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 - -- todo: prepend - v.commands = { { "slot", slot, idx } } - -- hack to prevent that type 3 also gets 'use' flags .. todo - local c = { commands = false, index = idx, dropin = tfmdrop } - local d = { } -- index = idx, dropin = tfmdrop } - setmetatableindex(c,v) - setmetatableindex(d,description) - dropchars[idx] = c - dropdescs[idx] = d -- not needed - end - end - end - else - -- error - end - end - -end - -do -- this will move to its own module - - local dropins = fonts.dropins - - local shapes = setmetatableindex(function(t,k) - local v = { - glyphs = { }, - parameters = { - units = 1000 - }, - } - t[k] = v - return v - end) - - function dropins.registerglyphs(parameters) - local category = parameters.name - local target = shapes[category].parameters - for k, v in next, parameters do - if k ~= "glyphs" then - target[k] = v - end - end - end - - function dropins.registerglyph(parameters) - local category = parameters.category - local unicode = parameters.unicode - local private = parameters.private - local unichar = parameters.unichar - if private then - unicode = fonts.helpers.newprivateslot(private) - elseif type(unichar) == "string" then - unicode = utfbyte(unichar) - else - local unitype = type(unicode) - if unitype == "string" then - local uninumber = tonumber(unicode) - if uninumber then - unicode = round(uninumber) - else - unicode = utfbyte(unicode) - end - elseif unitype == "number" then - unicode = round(unicode) - end - end - if unicode then - parameters.unicode = unicode - -- print(category,unicode) - shapes[category].glyphs[unicode] = parameters - else - -- error - end - end - - -- local function hascolorspec(t) - -- if (t.color or "") ~= "" then - -- return true - -- elseif (t.fillcolor or "") ~= "" then - -- return true - -- elseif (t.drawcolor or "") ~= "" then - -- return true - -- elseif (t.linecolor or "") ~= "" then - -- return true - -- else - -- return false - -- end - -- end - - local function hascolorspec(t) - for k, v in next, t do - if find(k,"color") then - return true - end - end - return false - end - - local function initializemps(tfmdata,kind,value) - if value then - local specification = settings_to_hash_strict(value) - if not specification or not next(specification) then - specification = { category = value } - end - -- todo: multiple categories but then maybe also different - -- clones because of the units .. for now we assume the same - -- units - local category = specification.category - if category and category ~= "" then - local categories = settings_to_array(category) - local usedshapes = nil - local index = 0 - local spread = tonumber(specification.spread or 0) - local hascolor = hascolorspec(specification) - specification.spread = spread -- now a number - for i=1,#categories do - local category = categories[i] - local mpsshapes = shapes[category] - if mpsshapes then - local properties = tfmdata.properties - local parameters = tfmdata.parameters - local characters = tfmdata.characters - local descriptions = tfmdata.descriptions - local mpsparameters = mpsshapes.parameters - local units = mpsparameters.units or 1000 - local defaultwidth = mpsparameters.width or 0 - local defaultheight = mpsparameters.height or 0 - local defaultdepth = mpsparameters.depth or 0 - local usecolor = mpsparameters.usecolor - local spread = spread * units - local defaultcode = mpsparameters.code or "" - local scale = parameters.size / units - if hascolor then - -- the graphic has color - usecolor = false - else - -- do whatever is specified - end - usedshapes = usedshapes or { - instance = "simplefun", - units = units, - usecolor = usecolor, - specification = specification, - shapes = mpsshapes, - } - -- todo: deal with extensibles and more properties - for unicode, shape in sortedhash(mpsshapes.glyphs) do - -- local oldc = characters[unicode] - -- if oldc then - index = index + 1 -- todo: somehow we end up with 2 as first entry after 0 - local wd = shape.width or defaultwidth - local ht = shape.height or defaultheight - local dp = shape.depth or defaultdepth - local newc = { - index = index, -- into usedshapes - width = scale * (wd + spread), - height = scale * ht, - depth = scale * dp, - unicode = unicode, - } - -- - characters [unicode] = newc - descriptions[unicode] = newc - -- - usedshapes[unicode] = shape.code or defaultcode - -- end - end - end - end - if usedshapes then - -- todo: different font when units and usecolor changes, maybe move into loop - -- above - dropins.swap("mps",tfmdata,usedshapes) - end - end - end - end - - -- This kicks in quite late, after features have been checked. So if needed - -- substitutions need to be defined with force. - - otfregister { - name = "metapost", - description = "metapost glyphs", - manipulators = { - base = initializemps, - node = initializemps, - } - } - -end - --- This sits here for historcal reasons so for now we keep it here. - -local startactualtext = nil -local stopactualtext = nil - -function otf.getactualtext(s) - if not startactualtext then - startactualtext = backends.codeinjections.startunicodetoactualtextdirect - stopactualtext = backends.codeinjections.stopunicodetoactualtextdirect - end - return startactualtext(s), stopactualtext() -end - --- This is also somewhat specific. - -local sharedpalettes do - - sharedpalettes = { } - - 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 - 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] = color(1,c) .. " " .. transparency(t) - elseif c then - values[i] = color(1,c) - elseif t then - values[i] = color(1,t) - end - end - end - end - -end - -local initializeoverlay do - - -- we should use the proper interface instead but for now: - - local colors = attributes.colors - local rgbtocmyk = colors.rgbtocmyk - - local f_cmyk = formatters["%.3N %.3f %.3N %.3N k"] - local f_rgb = formatters["%.3N %.3f %.3N rg"] - local f_gray = formatters["%.3N g"] - - local function convert(t,k) - local v = { } - local m = colors.model - for i=1,#k do - local p = k[i] - local r, g, b = p[1]/255, p[2]/255, p[3]/255 - if r == g and g == b then - p = f_gray(r) - elseif m == "cmyk" then - p = f_cmyk(rgbtocmyk(r,g,b)) - else - p = f_rgb(r,g,b) - end - v[i] = p - end - t[k] = v - return v - end - - initializeoverlay = function(tfmdata,kind,value) -- we really need the id ... todo - if value then - local resources = tfmdata.resources - local palettes = resources.colorpalettes - if palettes then - -- - local converted = resources.converted - if not converted then - 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 - if classes == 0 then - return - end - -- - local characters = tfmdata.characters - local descriptions = tfmdata.descriptions - local droppedin, tfmdrop, dropchars, dropdescs, colrshapes - local idx = 255 - local slot = 0 - -- - -- maybe delay in which case we have less fonts as we can be sparse - -- - for k, v in next, characters do - local index = v.index - if index then - local description = descriptions[k] - if description then - local colorlist = description.colors - if colorlist then - if idx >= 255 then - idx = 1 - colrshapes = { } - slot, droppedin, tfmdrop = fonts.dropins.provide("color",tfmdata,colrshapes,colorvalues) - dropchars = tfmdrop.characters - dropdescs = tfmdrop.descriptions - else - idx = idx + 1 - end - -- - colrshapes[idx] = description - -- todo: use extender - local u = { "use", 0 } - for i=1,#colorlist do - u[i+2] = colorlist[i].slot - end - v.commands = { u, { "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 = tfmdrop - setmetatableindex(c,v) - setmetatableindex(d,description) - dropchars[idx] = c - dropdescs[idx] = d -- not needed - end - end - end - end - return true - end - end - end - - fonts.handlers.otf.features.register { - name = "colr", - description = "color glyphs", - manipulators = { - base = initializeoverlay, - node = initializeoverlay, - } - } - -end - -local initializesvg do - - local report_svg = logs.reporter("fonts","svg") - - local cached = true -- maybe always false (after i've optimized the lot) - - directives.register("fonts.svg.cached", function(v) cached = v end) - - initializesvg = function(tfmdata,kind,value) -- hm, always value - if value then - local properties = tfmdata.properties - local svg = properties.svg - local hash = svg and svg.hash - local timestamp = svg and svg.timestamp - if not hash then - return - end - local shapes = nil - local method = nil - local enforce = attributes.colors.model == "cmyk" - if cached and not enforce then - -- we need a different hash than for mkiv, so we append: - local pdfhash = hash .. "-svg" - local pdffile = containers.read(otf.pdfcache,pdfhash) - local pdfshapes = pdffile and pdffile.pdfshapes - local pdftarget = file.join(otf.pdfcache.writable,file.addsuffix(pdfhash,"pdf")) - 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,tfmdata.parameters.units) or { } - -- look at ocl: we should store scale and x and y - containers.write(otf.pdfcache, pdfhash, { - pdfshapes = pdfshapes, - timestamp = timestamp, - }) - end - shapes = pdfshapes - method = "pdf" - else - local mpsfile = containers.read(otf.mpscache,hash) - local mpsshapes = mpsfile and mpsfile.mpsshapes - if not mpsshapes or mpsfile.timestamp ~= timestamp or not next(mpsshapes) then - local svgfile = containers.read(otf.svgcache,hash) - local svgshapes = svgfile and svgfile.svgshapes - -- still suboptimal - mpsshapes = svgshapes and metapost.svgshapestomp(svgshapes,report_svg,tfmdata.parameters.units) or { } - if enforce then - -- cheap conversion, no black component generation - mpsshapes.preamble = "interim svgforcecmyk := 1;" - end - containers.write(otf.mpscache, hash, { - mpsshapes = mpsshapes, - timestamp = timestamp, - }) - end - shapes = mpsshapes - method = "mps" - end - if shapes then - shapes.fixdepth = value == "fixdepth" - fonts.dropins.clone(method,tfmdata,shapes) - end - return true - end - end - - otfregister { - name = "svg", - description = "svg glyphs", - manipulators = { - base = initializesvg, - node = initializesvg, - } - } - -end - -local initializepng do - - -- If this is really critical we can also use a pdf file as cache but I don't expect - -- png fonts to remain used. - - local colors = attributes.colors - - local report_png = logs.reporter("fonts","png conversion") - - initializepng = function(tfmdata,kind,value) -- hm, always value - if value then - local properties = tfmdata.properties - local png = properties.png - local hash = png and png.hash - local timestamp = png and png.timestamp - if not hash then - return - end - local pngfile = containers.read(otf.pngcache,hash) - local pngshapes = pngfile and pngfile.pngshapes - if pngshapes then - if colors.model == "cmyk" then - pngshapes.enforcecmyk = true - end - fonts.dropins.clone("png",tfmdata,pngshapes) - end - return true - end - end - - otfregister { - name = "sbix", - description = "sbix glyphs", - manipulators = { - base = initializepng, - node = initializepng, - } - } - - otfregister { - name = "cblc", - description = "cblc glyphs", - manipulators = { - base = initializepng, - node = initializepng, - } - } - -end - -do - - -- I need to check jpeg and such but will do that when I run into - -- it. - - local function initializecolor(tfmdata,kind,value) - if value == "auto" then - return - initializeoverlay(tfmdata,kind,value) or - initializesvg(tfmdata,kind,value) or - initializepng(tfmdata,kind,value) - elseif value == "overlay" then - return initializeoverlay(tfmdata,kind,value) - elseif value == "svg" then - return initializesvg(tfmdata,kind,value) - elseif value == "png" or value == "bitmap" then - return initializepng(tfmdata,kind,value) - else - -- forget about it - end - end - - otfregister { - name = "color", - description = "color glyphs", - manipulators = { - base = initializecolor, - node = initializecolor, - } - } - -end |