From 81095dd1bf20eb5f7e126adbdc8047f940504180 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Mon, 20 Jul 2020 11:09:33 +0200 Subject: 2020-07-20 10:42:00 --- tex/context/base/mkii/cont-new.mkii | 2 +- tex/context/base/mkii/context.mkii | 2 +- tex/context/base/mkiv/back-lua.lmt | 366 + tex/context/base/mkiv/back-lua.lua | 355 - tex/context/base/mkiv/back-lua.mkxl | 2 +- tex/context/base/mkiv/back-mps.lmt | 210 + tex/context/base/mkiv/back-mps.lua | 206 - tex/context/base/mkiv/back-mps.mkxl | 2 +- tex/context/base/mkiv/back-out.lmt | 259 + tex/context/base/mkiv/back-out.lua | 259 - tex/context/base/mkiv/back-out.mkxl | 2 +- tex/context/base/mkiv/back-pdf.mkiv | 1 + tex/context/base/mkiv/back-pdf.mkxl | 8 +- tex/context/base/mkiv/cldf-ini.mkiv | 2 +- tex/context/base/mkiv/cldf-int.lmt | 252 + tex/context/base/mkiv/cldf-int.lua | 377 +- tex/context/base/mkiv/cldf-int.mkxl | 2 +- tex/context/base/mkiv/cldf-lmt.lmt | 720 + tex/context/base/mkiv/cldf-lmt.lua | 720 - tex/context/base/mkiv/colo-ini.mkxl | 75 +- tex/context/base/mkiv/cont-new.mkiv | 2 +- tex/context/base/mkiv/context.mkiv | 2 +- tex/context/base/mkiv/context.mkxl | 2 +- tex/context/base/mkiv/core-env.lua | 26 +- tex/context/base/mkiv/core-lmt.lmt | 34 + tex/context/base/mkiv/core-lmt.lua | 34 - tex/context/base/mkiv/core-lmt.mkxl | 2 +- tex/context/base/mkiv/driv-shp.lmt | 1361 ++ tex/context/base/mkiv/driv-shp.lua | 1337 -- tex/context/base/mkiv/driv-shp.mkxl | 2 +- tex/context/base/mkiv/font-con.lua | 9 + tex/context/base/mkiv/font-imp-effects.lua | 68 +- tex/context/base/mkiv/font-imp-tracing.lua | 60 +- tex/context/base/mkiv/font-lib.mkvi | 2 +- tex/context/base/mkiv/font-ogr.lmt | 672 + tex/context/base/mkiv/font-ogr.lua | 672 - tex/context/base/mkiv/font-otr.lua | 1 + tex/context/base/mkiv/grph-inc.lua | 6 +- tex/context/base/mkiv/grph-inc.mkiv | 6 +- tex/context/base/mkiv/libs-imp-curl.lmt | 296 + tex/context/base/mkiv/libs-imp-curl.lua | 296 - tex/context/base/mkiv/libs-imp-ghostscript.lmt | 111 + tex/context/base/mkiv/libs-imp-ghostscript.lua | 111 - tex/context/base/mkiv/libs-imp-graphicsmagick.lmt | 77 + tex/context/base/mkiv/libs-imp-graphicsmagick.lua | 77 - tex/context/base/mkiv/libs-imp-kpse.lmt | 58 + tex/context/base/mkiv/libs-imp-kpse.lua | 58 - tex/context/base/mkiv/libs-imp-kpse.mkxl | 2 +- tex/context/base/mkiv/libs-imp-mujs.lmt | 126 + tex/context/base/mkiv/libs-imp-mujs.lua | 126 - tex/context/base/mkiv/libs-imp-mujs.mkxl | 2 +- tex/context/base/mkiv/libs-imp-mysql.lmt | 220 + tex/context/base/mkiv/libs-imp-mysql.lua | 220 - tex/context/base/mkiv/libs-imp-postgress.lmt | 200 + tex/context/base/mkiv/libs-imp-postgress.lua | 200 - tex/context/base/mkiv/libs-imp-sqlite.lmt | 187 + tex/context/base/mkiv/libs-imp-sqlite.lua | 187 - tex/context/base/mkiv/libs-imp-zint.lmt | 161 + tex/context/base/mkiv/libs-imp-zint.lua | 161 - tex/context/base/mkiv/libs-imp-zint.mkxl | 2 +- tex/context/base/mkiv/libs-ini.lua | 18 +- tex/context/base/mkiv/libs-ini.mkxl | 15 +- tex/context/base/mkiv/lpdf-ano.lua | 3 +- tex/context/base/mkiv/lpdf-col.lua | 10 +- tex/context/base/mkiv/lpdf-emb.lmt | 2225 ++++ tex/context/base/mkiv/lpdf-emb.lua | 2225 ---- tex/context/base/mkiv/lpdf-img.lmt | 1341 ++ tex/context/base/mkiv/lpdf-img.lua | 1341 -- tex/context/base/mkiv/lpdf-ini.lua | 18 +- tex/context/base/mkiv/lpdf-lmt.lmt | 2835 ++++ tex/context/base/mkiv/lpdf-lmt.lua | 2798 ---- tex/context/base/mkiv/lpdf-vfc.lmt | 40 + tex/context/base/mkiv/lpdf-vfc.lua | 50 + tex/context/base/mkiv/mlib-ctx.mkiv | 1 + tex/context/base/mkiv/mlib-ctx.mkxl | 1 + tex/context/base/mkiv/mlib-fio.lmt | 191 + tex/context/base/mkiv/mlib-fio.lua | 85 + tex/context/base/mkiv/mlib-lua.lmt | 49 +- tex/context/base/mkiv/mlib-run.lua | 246 +- tex/context/base/mkiv/mlib-scn.lmt | 21 +- tex/context/base/mkiv/mult-def.lua | 13136 ++++++++++--------- tex/context/base/mkiv/mult-low.lua | 2 +- tex/context/base/mkiv/node-aux.lua | 158 - tex/context/base/mkiv/node-cmp.lmt | 243 + tex/context/base/mkiv/node-cmp.lua | 243 - tex/context/base/mkiv/node-gcm.lmt | 107 + tex/context/base/mkiv/node-gcm.lua | 91 + tex/context/base/mkiv/node-ini.mkiv | 3 +- tex/context/base/mkiv/pack-ori.lmt | 70 + tex/context/base/mkiv/pack-ori.lua | 70 - tex/context/base/mkiv/pack-ori.mkxl | 2 +- tex/context/base/mkiv/status-files.pdf | Bin 27734 -> 28069 bytes tex/context/base/mkiv/status-lua.pdf | Bin 255207 -> 254724 bytes tex/context/base/mkiv/supp-ran.lua | 14 +- tex/context/base/mkiv/supp-ran.mkiv | 22 +- tex/context/base/mkiv/syst-aux.lua | 119 - tex/context/base/mkiv/syst-aux.mkiv | 1 + tex/context/base/mkiv/syst-aux.mkxl | 1 + tex/context/base/mkiv/syst-ini.mkiv | 7 +- tex/context/base/mkiv/syst-ini.mkxl | 7 +- tex/context/base/mkiv/syst-lua.lmt | 315 + tex/context/base/mkiv/syst-lua.lua | 211 +- tex/context/base/mkiv/syst-lua.mkxl | 2 +- tex/context/base/mkiv/syst-mac.lmt | 117 + tex/context/base/mkiv/syst-mac.lua | 9 + tex/context/base/mkiv/toks-aux.lua | 144 +- tex/context/base/mkiv/toks-aux.mkiv | 4 +- tex/context/base/mkiv/trac-vis.lua | 15 +- tex/context/modules/mkiv/m-sql.mkiv | 4 +- tex/context/modules/mkiv/m-steps.mkvi | 40 +- tex/context/modules/mkiv/s-system-visual.mkiv | 94 + tex/generic/context/luatex/luatex-fonts-merged.lua | 69 +- 112 files changed, 20584 insertions(+), 19247 deletions(-) create mode 100644 tex/context/base/mkiv/back-lua.lmt delete mode 100644 tex/context/base/mkiv/back-lua.lua create mode 100644 tex/context/base/mkiv/back-mps.lmt delete mode 100644 tex/context/base/mkiv/back-mps.lua create mode 100644 tex/context/base/mkiv/back-out.lmt delete mode 100644 tex/context/base/mkiv/back-out.lua create mode 100644 tex/context/base/mkiv/cldf-int.lmt create mode 100644 tex/context/base/mkiv/cldf-lmt.lmt delete mode 100644 tex/context/base/mkiv/cldf-lmt.lua create mode 100644 tex/context/base/mkiv/core-lmt.lmt delete mode 100644 tex/context/base/mkiv/core-lmt.lua create mode 100644 tex/context/base/mkiv/driv-shp.lmt delete mode 100644 tex/context/base/mkiv/driv-shp.lua create mode 100644 tex/context/base/mkiv/font-ogr.lmt delete mode 100644 tex/context/base/mkiv/font-ogr.lua create mode 100644 tex/context/base/mkiv/libs-imp-curl.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-curl.lua create mode 100644 tex/context/base/mkiv/libs-imp-ghostscript.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-ghostscript.lua create mode 100644 tex/context/base/mkiv/libs-imp-graphicsmagick.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-graphicsmagick.lua create mode 100644 tex/context/base/mkiv/libs-imp-kpse.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-kpse.lua create mode 100644 tex/context/base/mkiv/libs-imp-mujs.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-mujs.lua create mode 100644 tex/context/base/mkiv/libs-imp-mysql.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-mysql.lua create mode 100644 tex/context/base/mkiv/libs-imp-postgress.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-postgress.lua create mode 100644 tex/context/base/mkiv/libs-imp-sqlite.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-sqlite.lua create mode 100644 tex/context/base/mkiv/libs-imp-zint.lmt delete mode 100644 tex/context/base/mkiv/libs-imp-zint.lua create mode 100644 tex/context/base/mkiv/lpdf-emb.lmt delete mode 100644 tex/context/base/mkiv/lpdf-emb.lua create mode 100644 tex/context/base/mkiv/lpdf-img.lmt delete mode 100644 tex/context/base/mkiv/lpdf-img.lua create mode 100644 tex/context/base/mkiv/lpdf-lmt.lmt delete mode 100644 tex/context/base/mkiv/lpdf-lmt.lua create mode 100644 tex/context/base/mkiv/lpdf-vfc.lmt create mode 100644 tex/context/base/mkiv/lpdf-vfc.lua create mode 100644 tex/context/base/mkiv/mlib-fio.lmt create mode 100644 tex/context/base/mkiv/mlib-fio.lua create mode 100644 tex/context/base/mkiv/node-cmp.lmt delete mode 100644 tex/context/base/mkiv/node-cmp.lua create mode 100644 tex/context/base/mkiv/node-gcm.lmt create mode 100644 tex/context/base/mkiv/node-gcm.lua create mode 100644 tex/context/base/mkiv/pack-ori.lmt delete mode 100644 tex/context/base/mkiv/pack-ori.lua create mode 100644 tex/context/base/mkiv/syst-lua.lmt create mode 100644 tex/context/base/mkiv/syst-mac.lmt create mode 100644 tex/context/base/mkiv/syst-mac.lua create mode 100644 tex/context/modules/mkiv/s-system-visual.mkiv (limited to 'tex') diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index bc18e3c22..c377cbe88 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{2020.07.13 23:44} +\newcontextversion{2020.07.20 10:40} %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 f45afe0a8..1ebb35693 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{2020.07.13 23:44} +\edef\contextversion{2020.07.20 10:40} %D For those who want to use this: diff --git a/tex/context/base/mkiv/back-lua.lmt b/tex/context/base/mkiv/back-lua.lmt new file mode 100644 index 000000000..dc836f12b --- /dev/null +++ b/tex/context/base/mkiv/back-lua.lmt @@ -0,0 +1,366 @@ +if not modules then modules = { } end modules ['back-lua'] = { + version = 1.001, + optimize = true, + 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" +} + +-- we can remap fonts + +local fontproperties = fonts.hashes.properties +local fontparameters = fonts.hashes.parameters +local fontshapes = fonts.hashes.shapes + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming + +local bpfactor = number.dimenfactors.bp +local texgetbox = tex.getbox + +local rulecodes = nodes.rulecodes +local normalrule_code = rulecodes.normal +----- boxrule_code = rulecodes.box +----- imagerule_code = rulecodes.image +----- emptyrule_code = rulecodes.empty +----- userrule_code = rulecodes.user +----- overrule_code = rulecodes.over +----- underrule_code = rulecodes.under +----- fractionrule_code = rulecodes.fraction +----- radicalrule_code = rulecodes.radical +local outlinerule_code = rulecodes.outline + +-- todo : per instance + +local pages = { } +local fonts = { } +local names = { } +local mapping = { } +local used = { } +local shapes = { } +local glyphs = { } +local buffer = { } +local b = 0 +local converter = nil + +local compact = false -- true +local shapestoo = true + +local x, y, d, f, c, w, h, t, r, o + +local function reset() + buffer = { } + b = 0 + t = nil + x = nil + y = nil + d = nil + f = nil + c = nil + w = nil + h = nil + r = nil + o = nil +end + +local function result() + -- todo: we're now still in the pdf backend but need different codeinjections + local codeinjections = backends.pdf.codeinjections + local getvariable = codeinjections.getidentityvariable or function() end + local jobname = environment.jobname or tex.jobname or "unknown" + return { + metadata = { + unit = "bp", + jobname = jobname, + title = getvariable("title") or jobname, + subject = getvariable("subject"), + author = getvariable("author"), + keywords = getvariable("keywords"), + time = os.date("%Y-%m-%d %H:%M"), + engine = environment.luatexengine .. " " .. environment.luatexversion, + context = environment.version, + }, + fonts = fonts, + pages = pages, + shapes = shapes, + } +end + +-- actions + +local function outputfilename(driver) + return tex.jobname .. "-output.lua" +end + +local function save() -- might become a driver function that already is plugged into stopactions + local filename = outputfilename() + drivers.report("saving result in %a",filename) + starttiming(drivers) + local data = result() + if data then + io.savedata(filename,table.serialize(data)) + end + stoptiming(drivers) +end + +local function prepare(driver) + converter = drivers.converters.lmtx + luatex.registerstopactions(1,function() + save() + end) +end + +local function initialize(driver,details) + reset() +end + +local function finalize(driver,details) + local n = details.pagenumber + local b = details.boundingbox + pages[n] = { + number = n, + content = buffer, + boundingbox = { + b[1] * bpfactor, + b[2] * bpfactor, + b[3] * bpfactor, + b[4] * bpfactor, + }, + } +end + +local function wrapup(driver) +end + +local function cleanup(driver) + reset() +end + +local function convert(driver,boxnumber,pagenumber) + converter(driver,texgetbox(boxnumber),"page",pagenumber) +end + +-- flushers + +local function updatefontstate(id) + if not mapping[id] then + local fn = #fonts + 1 + mapping[id] = fn + local properties = fontproperties[id] + local parameters = fontparameters[id] + local filename = file.basename(properties.filename) + local fontname = properties.fullname or properties.fontname + if shapestoo then + if not names[fontname] then + local sn = #shapes+1 + names[fontname] = sn + shapes[sn] = { } + glyphs[sn] = fontshapes[id].glyphs + end + end + fonts[fn] = { + filename = filename, + name = fontname, + size = parameters.size * bpfactor, + shapes = shapestoo and names[fontname] or nil, + } + end +end + +local function flushcharacter(current, pos_h, pos_v, pos_r, font, char) + local fnt = mapping[font] + b = b + 1 + buffer[b] = { + t = "glyph" ~= t and "glyph" or nil, + f = font ~= f and fnt or nil, + c = char ~= c and char or nil, + x = pos_h ~= x and (pos_h * bpfactor) or nil, + y = pos_v ~= y and (pos_v * bpfactor) or nil, + d = pos_r ~= d and (pos_r == 1 and "r2l" or "l2r") or nil, + } + t = "glyph" + f = font + c = char + x = pos_h + y = pos_v + d = pos_r + if shapestoo then + -- can be sped up if needed + local sn = fonts[fnt].shapes + local shp = shapes[sn] + if not shp[char] then + shp[char] = glyphs[sn][char] + end + end +end + +local function rule(pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o) + b = b + 1 + buffer[b] = { + t = "rule" ~= t and "rule" or nil, + r = rule_s ~= r and rule_s or nil, + o = rule_s == "outline" and rule_o ~= o and (rule_o * bpfactor) or nil, + w = size_h ~= w and (size_h * bpfactor) or nil, + h = size_v ~= h and (size_v * bpfactor) or nil, + x = pos_h ~= x and (pos_h * bpfactor) or nil, + y = pos_v ~= y and (pos_v * bpfactor) or nil, + d = pos_r ~= d and (pos_r == 1 and "r2l" or "l2r") or nil, + } + t = "rule" + w = size_h + h = size_v + x = pos_h + y = pos_v + d = pos_r +end + +local function flushrule(current, pos_h, pos_v, pos_r, size_h, size_v, subtype) + local rule_s, rule_o + if subtype == normalrule_code then + rule_s = "normal" + elseif subtype == outlinerule_code then + rule_s = "outline" + rule_o = getdata(current) + else + return + end + return rule(pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o) +end + +local function flushsimplerule(pos_h, pos_v, pos_r, size_h, size_v) + return rule(pos_h, pos_v, pos_r, size_h, size_v, "normal", nil) +end + +local function flushspecialrule(pos_h, pos_v, pos_r, w, h, d, l, outline) + -- no l support yet + return rule(pos_h, pos_v - d, pos_r, w, h + d, outline and "outline" or "normal") +end + +-- file stuff too +-- todo: default flushers +-- also color (via hash) + +-- installer + +drivers.install { + name = "lua", + actions = { + prepare = prepare, + initialize = initialize, + finalize = finalize, + wrapup = wrapup, + cleanup = cleanup, + convert = convert, + outputfilename = outputfilename, + }, + flushers = { + updatefontstate = updatefontstate, + character = flushcharacter, + rule = flushrule, + simplerule = flushsimplerule, + specialrule = flushspecialrule, + } +} + +-- actions + +local function outputfilename(driver) + return tex.jobname .. "-output.json" +end + +local function save() -- might become a driver function that already is plugged into stopactions + local filename = outputfilename() + drivers.report("saving result in %a",filename) + starttiming(drivers) + local data = result() + if data then + if not utilities.json then + require("util-jsn") + end + io.savedata(filename,utilities.json.tostring(data,not compact)) + end + stoptiming(drivers) +end + +local function prepare(driver) + converter = drivers.converters.lmtx + luatex.registerstopactions(1,function() + save() + end) +end + +-- installer + +drivers.install { + name = "json", + actions = { + prepare = prepare, + initialize = initialize, + finalize = finalize, + wrapup = wrapup, + cleanup = cleanup, + convert = convert, + outputfilename = outputfilename, + }, + flushers = { + updatefontstate = updatefontstate, + character = flushcharacter, + rule = flushrule, + simplerule = flushsimplerule, + specialrule = flushspecialrule, + } +} + +-- actions + +local function outputfilename(driver) + return tex.jobname .. "-output.js" +end + +local function save() -- might become a driver function that already is plugged into stopactions + local filename = outputfilename() + drivers.report("saving result in %a",filename) + starttiming(drivers) + local data = result() + if data then + if not utilities.json then + require("util-jsn") + end + io.savedata(filename, + "const JSON_CONTEXT = JSON.parse ( `" .. + utilities.json.tostring(data,not compact) .. + "` ) ;\n" + ) + end + stoptiming(drivers) +end + +local function prepare(driver) + converter = drivers.converters.lmtx + luatex.registerstopactions(1,function() + save() + end) +end + +-- installer + +drivers.install { + name = "js", + actions = { + prepare = prepare, + initialize = initialize, + finalize = finalize, + wrapup = wrapup, + cleanup = cleanup, + convert = convert, + outputfilename = outputfilename, + }, + flushers = { + updatefontstate = updatefontstate, + character = flushcharacter, + rule = flushrule, + simplerule = flushsimplerule, + specialrule = flushspecialrule, + } +} diff --git a/tex/context/base/mkiv/back-lua.lua b/tex/context/base/mkiv/back-lua.lua deleted file mode 100644 index 87093afd4..000000000 --- a/tex/context/base/mkiv/back-lua.lua +++ /dev/null @@ -1,355 +0,0 @@ -if not modules then modules = { } end modules ['back-lua'] = { - version = 1.001, - optimize = true, - 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" -} - --- we can remap fonts - -local fontproperties = fonts.hashes.properties -local fontparameters = fonts.hashes.parameters -local fontshapes = fonts.hashes.shapes - -local starttiming = statistics.starttiming -local stoptiming = statistics.stoptiming - -local bpfactor = number.dimenfactors.bp -local texgetbox = tex.getbox - -local rulecodes = nodes.rulecodes -local normalrule_code = rulecodes.normal ------ boxrule_code = rulecodes.box ------ imagerule_code = rulecodes.image ------ emptyrule_code = rulecodes.empty ------ userrule_code = rulecodes.user ------ overrule_code = rulecodes.over ------ underrule_code = rulecodes.under ------ fractionrule_code = rulecodes.fraction ------ radicalrule_code = rulecodes.radical -local outlinerule_code = rulecodes.outline - --- todo : per instance - -local pages = { } -local fonts = { } -local names = { } -local mapping = { } -local used = { } -local shapes = { } -local glyphs = { } -local buffer = { } -local b = 0 -local converter = nil - -local compact = false -- true -local shapestoo = true - -local x, y, d, f, c, w, h, t, r, o - -local function reset() - buffer = { } - b = 0 - t = nil - x = nil - y = nil - d = nil - f = nil - c = nil - w = nil - h = nil - r = nil - o = nil -end - -local function result() - -- todo: we're now still in the pdf backend but need different codeinjections - local codeinjections = backends.pdf.codeinjections - local getvariable = codeinjections.getidentityvariable or function() end - local jobname = environment.jobname or tex.jobname or "unknown" - return { - metadata = { - unit = "bp", - jobname = jobname, - title = getvariable("title") or jobname, - subject = getvariable("subject"), - author = getvariable("author"), - keywords = getvariable("keywords"), - time = os.date("%Y-%m-%d %H:%M"), - engine = environment.luatexengine .. " " .. environment.luatexversion, - context = environment.version, - }, - fonts = fonts, - pages = pages, - shapes = shapes, - } -end - --- actions - -local function outputfilename(driver) - return tex.jobname .. "-output.lua" -end - -local function save() -- might become a driver function that already is plugged into stopactions - local filename = outputfilename() - drivers.report("saving result in %a",filename) - starttiming(drivers) - local data = result() - if data then - io.savedata(filename,table.serialize(data)) - end - stoptiming(drivers) -end - -local function prepare(driver) - converter = drivers.converters.lmtx - luatex.registerstopactions(1,function() - save() - end) -end - -local function initialize(driver,details) - reset() -end - -local function finalize(driver,details) - local n = details.pagenumber - local b = details.boundingbox - pages[n] = { - number = n, - content = buffer, - boundingbox = { - b[1] * bpfactor, - b[2] * bpfactor, - b[3] * bpfactor, - b[4] * bpfactor, - }, - } -end - -local function wrapup(driver) -end - -local function cleanup(driver) - reset() -end - -local function convert(driver,boxnumber,pagenumber) - converter(driver,texgetbox(boxnumber),"page",pagenumber) -end - --- flushers - -local function updatefontstate(id) - if not mapping[id] then - local fn = #fonts + 1 - mapping[id] = fn - local properties = fontproperties[id] - local parameters = fontparameters[id] - local filename = file.basename(properties.filename) - local fontname = properties.fullname or properties.fontname - if shapestoo then - if not names[fontname] then - local sn = #shapes+1 - names[fontname] = sn - shapes[sn] = { } - glyphs[sn] = fontshapes[id].glyphs - end - end - fonts[fn] = { - filename = filename, - name = fontname, - size = parameters.size * bpfactor, - shapes = shapestoo and names[fontname] or nil, - } - end -end - -local function flushcharacter(current, pos_h, pos_v, pos_r, font, char) - local fnt = mapping[font] - b = b + 1 - buffer[b] = { - t = "glyph" ~= t and "glyph" or nil, - f = font ~= f and fnt or nil, - c = char ~= c and char or nil, - x = pos_h ~= x and (pos_h * bpfactor) or nil, - y = pos_v ~= y and (pos_v * bpfactor) or nil, - d = pos_r ~= d and (pos_r == 1 and "r2l" or "l2r") or nil, - } - t = "glyph" - f = font - c = char - x = pos_h - y = pos_v - d = pos_r - if shapestoo then - -- can be sped up if needed - local sn = fonts[fnt].shapes - local shp = shapes[sn] - if not shp[char] then - shp[char] = glyphs[sn][char] - end - end -end - -local function rule(pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o) - b = b + 1 - buffer[b] = { - t = "rule" ~= t and "rule" or nil, - r = rule_s ~= r and rule_s or nil, - o = rule_s == "outline" and rule_o ~= o and (rule_o * bpfactor) or nil, - w = size_h ~= w and (size_h * bpfactor) or nil, - h = size_v ~= h and (size_v * bpfactor) or nil, - x = pos_h ~= x and (pos_h * bpfactor) or nil, - y = pos_v ~= y and (pos_v * bpfactor) or nil, - d = pos_r ~= d and (pos_r == 1 and "r2l" or "l2r") or nil, - } - t = "rule" - w = size_h - h = size_v - x = pos_h - y = pos_v - d = pos_r -end - -local function flushrule(current, pos_h, pos_v, pos_r, size_h, size_v, subtype) - local rule_s, rule_o - if subtype == normalrule_code then - rule_s = "normal" - elseif subtype == outlinerule_code then - rule_s = "outline" - rule_o = getdata(current) - else - return - end - return rule(pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o) -end - -local function flushsimplerule(current, pos_h, pos_v, pos_r, size_h, size_v) - return rule(pos_h, pos_v, pos_r, size_h, size_v, "normal", nil) -end - --- file stuff too --- todo: default flushers --- also color (via hash) - --- installer - -drivers.install { - name = "lua", - actions = { - prepare = prepare, - initialize = initialize, - finalize = finalize, - wrapup = wrapup, - cleanup = cleanup, - convert = convert, - outputfilename = outputfilename, - }, - flushers = { - updatefontstate = updatefontstate, - character = flushcharacter, - rule = flushrule, - } -} - --- actions - -local function outputfilename(driver) - return tex.jobname .. "-output.json" -end - -local function save() -- might become a driver function that already is plugged into stopactions - local filename = outputfilename() - drivers.report("saving result in %a",filename) - starttiming(drivers) - local data = result() - if data then - if not utilities.json then - require("util-jsn") - end - io.savedata(filename,utilities.json.tostring(data,not compact)) - end - stoptiming(drivers) -end - -local function prepare(driver) - converter = drivers.converters.lmtx - luatex.registerstopactions(1,function() - save() - end) -end - --- installer - -drivers.install { - name = "json", - actions = { - prepare = prepare, - initialize = initialize, - finalize = finalize, - wrapup = wrapup, - cleanup = cleanup, - convert = convert, - outputfilename = outputfilename, - }, - flushers = { - updatefontstate = updatefontstate, - character = flushcharacter, - rule = flushrule, - } -} - --- actions - -local function outputfilename(driver) - return tex.jobname .. "-output.js" -end - -local function save() -- might become a driver function that already is plugged into stopactions - local filename = outputfilename() - drivers.report("saving result in %a",filename) - starttiming(drivers) - local data = result() - if data then - if not utilities.json then - require("util-jsn") - end - io.savedata(filename, - "const JSON_CONTEXT = JSON.parse ( `" .. - utilities.json.tostring(data,not compact) .. - "` ) ;\n" - ) - end - stoptiming(drivers) -end - -local function prepare(driver) - converter = drivers.converters.lmtx - luatex.registerstopactions(1,function() - save() - end) -end - --- installer - -drivers.install { - name = "js", - actions = { - prepare = prepare, - initialize = initialize, - finalize = finalize, - wrapup = wrapup, - cleanup = cleanup, - convert = convert, - outputfilename = outputfilename, - }, - flushers = { - updatefontstate = updatefontstate, - character = flushcharacter, - rule = flushrule, - } -} diff --git a/tex/context/base/mkiv/back-lua.mkxl b/tex/context/base/mkiv/back-lua.mkxl index 82ba8f9f1..6c5aaf82c 100644 --- a/tex/context/base/mkiv/back-lua.mkxl +++ b/tex/context/base/mkiv/back-lua.mkxl @@ -12,7 +12,7 @@ %C details. \ifcase\contextlmtxmode \else - \registerctxluafile{back-lua}{optimize} + \registerctxluafile{back-lua}{autosuffix,optimize} \fi \endinput diff --git a/tex/context/base/mkiv/back-mps.lmt b/tex/context/base/mkiv/back-mps.lmt new file mode 100644 index 000000000..4a2a573c4 --- /dev/null +++ b/tex/context/base/mkiv/back-mps.lmt @@ -0,0 +1,210 @@ +if not modules then modules = { } end modules ['back-mps'] = { + version = 1.001, + optimize = true, + 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 fontproperties = fonts.hashes.properties +local fontparameters = fonts.hashes.parameters + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming + +local bpfactor = number.dimenfactors.bp +local texgetbox = tex.getbox +local formatters = string.formatters + +local rulecodes = nodes.rulecodes +local normalrule_code = rulecodes.normal +----- boxrule_code = rulecodes.box +----- imagerule_code = rulecodes.image +----- emptyrule_code = rulecodes.empty +----- userrule_code = rulecodes.user +----- overrule_code = rulecodes.over +----- underrule_code = rulecodes.under +----- fractionrule_code = rulecodes.fraction +----- radicalrule_code = rulecodes.radical +local outlinerule_code = rulecodes.outline + +local fonts = { } +local pages = { } +local buffer = { } +local b = 0 +local converter = nil + +local function reset() + buffer = { } + b = 0 +end + +local f_font = formatters[ "\\definefont[%s][file:%s*none @ %sbp]\n" ] + +local f_glyph = formatters[ [[draw textext.drt("\%s\char%i\relax") shifted (%N,%N);]] ] +local f_rule = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ] +local f_outline = formatters[ [[draw unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ] + +-- actions + +local function outputfilename(driver) + return tex.jobname .. "-output.tex" +end + +local function save() -- might become a driver function that already is plugged into stopactions + starttiming(drivers) + if #pages > 0 then + local filename = outputfilename() + drivers.report("saving result in %a",filename) + reset() + b = b + 1 + buffer[b] = "\\starttext\n" + for k, v in table.sortedhash(fonts) do + b = b + 1 + buffer[b] = f_font(v.name,v.filename,v.size) + end + for i=1,#pages do + b = b + 1 + buffer[b] = pages[i] + end + b = b + 1 + buffer[b] = "\\stoptext\n" + io.savedata(filename,table.concat(buffer,"",1,b)) + end + stoptiming(drivers) +end + +local function prepare(driver) + converter = drivers.converters.lmtx + luatex.registerstopactions(1,function() + save() + end) +end + +local function initialize(driver,details) + reset() + b = b + 1 + buffer[b] = "\n\\startMPpage" +end + +local function finalize(driver,details) + b = b + 1 + buffer[b] = "\\stopMPpage\n" + pages[details.pagenumber] = table.concat(buffer,"\n",1,b) +end + +local function wrapup(driver) +end + +local function cleanup(driver) + reset() +end + +local function convert(driver,boxnumber,pagenumber) + converter(driver,texgetbox(boxnumber),"page",pagenumber) +end + +-- flushers + +local last + +local function updatefontstate(id) + if fonts[id] then + last = fonts[id].name + else + last = "MPSfont" .. converters.Characters(id) + fonts[id] = { + filename = file.basename(fontproperties[id].filename), + size = fontparameters[id].size * bpfactor, + name = last, + } + end +end + +local function flushcharacter(current, pos_h, pos_v, pod_r, font, char) + b = b + 1 + buffer[b] = f_glyph(last,char,pos_h*bpfactor,pos_v*bpfactor) +end + +local function flushrule(current, pos_h, pos_v, pod_r, size_h, size_v, subtype) + if subtype == normalrule_code then + b = b + 1 + buffer[b] = f_rule(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor) + elseif subtype == outlinerule_code then + b = b + 1 + buffer[b] = f_outline(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor) + end +end + +local function flushsimplerule(pos_h, pos_v, pod_r, size_h, size_v) + flush_rule(false,pos_h,pos_v,pod_r,size_h,size_v,normalrule_code) +end + +local function flushspecialrule(pos_h, pos_v, pod_r, w, h, d, l, outline) + flush_rule(false,pos_h,pos_v-d,pod_r,w,h+d,outline and outlinerule_code or normalrule_code) +end + +-- installer + +drivers.install { + name = "mps", + actions = { + prepare = prepare, + initialize = initialize, + finalize = finalize, + wrapup = wrapup, + cleanup = cleanup, + convert = convert, + outputfilename = outputfilename, + }, + flushers = { + updatefontstate = updatefontstate, + character = flushcharacter, + rule = flushrule, + simplerule = flushsimplerule, + specialrule = flushspecialrule, + } +} + +-- extras + +-- if not mp then +-- return +-- end +-- +-- local mpprint = mp.print +-- local formatters = string.formatters +-- +-- local f_glyph = formatters[ [[draw textext.drt("\setfontid%i\relax\char%i\relax") shifted (%N,%N);]] ] +-- local f_rule = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ] +-- +-- local current = nil +-- local size = 0 +-- +-- function mp.place_buffermake(box) +-- drivers.convert("mps",box) +-- current = drivers.action("mps","fetch") +-- size = #current +-- end +-- +-- function mp.place_buffersize() +-- mpprint(size) +-- end +-- +-- function mp.place_bufferslot(i) +-- if i > 0 and i <= size then +-- local b = buffer[i] +-- local t = b[1] +-- if t == "glyph" then +-- mpprint(f_glyph(b[2],b[3],b[4]*bpfactor,b[5]*bpfactor)) +-- elseif t == "rule" then +-- mpprint(f_rule(b[2]*bpfactor,b[3]*bpfactor,b[4]*bpfactor,b[5]*bpfactor)) +-- end +-- end +-- end +-- +-- function mp.place_bufferwipe() +-- current = nil +-- size = 0 +-- end diff --git a/tex/context/base/mkiv/back-mps.lua b/tex/context/base/mkiv/back-mps.lua deleted file mode 100644 index 13a0d6d42..000000000 --- a/tex/context/base/mkiv/back-mps.lua +++ /dev/null @@ -1,206 +0,0 @@ -if not modules then modules = { } end modules ['back-mps'] = { - version = 1.001, - optimize = true, - 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 fontproperties = fonts.hashes.properties -local fontparameters = fonts.hashes.parameters - -local starttiming = statistics.starttiming -local stoptiming = statistics.stoptiming - -local bpfactor = number.dimenfactors.bp -local texgetbox = tex.getbox -local formatters = string.formatters - -local rulecodes = nodes.rulecodes -local normalrule_code = rulecodes.normal ------ boxrule_code = rulecodes.box ------ imagerule_code = rulecodes.image ------ emptyrule_code = rulecodes.empty ------ userrule_code = rulecodes.user ------ overrule_code = rulecodes.over ------ underrule_code = rulecodes.under ------ fractionrule_code = rulecodes.fraction ------ radicalrule_code = rulecodes.radical -local outlinerule_code = rulecodes.outline - -local fonts = { } -local pages = { } -local buffer = { } -local b = 0 -local converter = nil - -local function reset() - buffer = { } - b = 0 -end - -local f_font = formatters[ "\\definefont[%s][file:%s*none @ %sbp]\n" ] - -local f_glyph = formatters[ [[draw textext.drt("\%s\char%i\relax") shifted (%N,%N);]] ] -local f_rule = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ] -local f_outline = formatters[ [[draw unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ] - --- actions - -local function outputfilename(driver) - return tex.jobname .. "-output.tex" -end - -local function save() -- might become a driver function that already is plugged into stopactions - starttiming(drivers) - if #pages > 0 then - local filename = outputfilename() - drivers.report("saving result in %a",filename) - reset() - b = b + 1 - buffer[b] = "\\starttext\n" - for k, v in table.sortedhash(fonts) do - b = b + 1 - buffer[b] = f_font(v.name,v.filename,v.size) - end - for i=1,#pages do - b = b + 1 - buffer[b] = pages[i] - end - b = b + 1 - buffer[b] = "\\stoptext\n" - io.savedata(filename,table.concat(buffer,"",1,b)) - end - stoptiming(drivers) -end - -local function prepare(driver) - converter = drivers.converters.lmtx - luatex.registerstopactions(1,function() - save() - end) -end - -local function initialize(driver,details) - reset() - b = b + 1 - buffer[b] = "\n\\startMPpage" -end - -local function finalize(driver,details) - b = b + 1 - buffer[b] = "\\stopMPpage\n" - pages[details.pagenumber] = table.concat(buffer,"\n",1,b) -end - -local function wrapup(driver) -end - -local function cleanup(driver) - reset() -end - -local function convert(driver,boxnumber,pagenumber) - converter(driver,texgetbox(boxnumber),"page",pagenumber) -end - --- flushers - -local last - -local function updatefontstate(id) - if fonts[id] then - last = fonts[id].name - else - last = "MPSfont" .. converters.Characters(id) - fonts[id] = { - filename = file.basename(fontproperties[id].filename), - size = fontparameters[id].size * bpfactor, - name = last, - } - end -end - -local function flushcharacter(current, pos_h, pos_v, pod_r, font, char) - b = b + 1 - buffer[b] = f_glyph(last,char,pos_h*bpfactor,pos_v*bpfactor) -end - -local function flushrule(current, pos_h, pos_v, pod_r, size_h, size_v, subtype) - if subtype == normalrule_code then - b = b + 1 - buffer[b] = f_rule(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor) - elseif subtype == outlinerule_code then - b = b + 1 - buffer[b] = f_outline(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor) - end -end - -local function flushsimplerule(current, pos_h, pos_v, pod_r, size_h, size_v) - b = b + 1 - buffer[b] = f_rule(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor) -end - --- installer - -drivers.install { - name = "mps", - actions = { - prepare = prepare, - initialize = initialize, - finalize = finalize, - wrapup = wrapup, - cleanup = cleanup, - convert = convert, - outputfilename = outputfilename, - }, - flushers = { - updatefontstate = updatefontstate, - character = flushcharacter, - rule = flushrule, - simplerule = flushsimplerule, - } -} - --- extras - --- if not mp then --- return --- end --- --- local mpprint = mp.print --- local formatters = string.formatters --- --- local f_glyph = formatters[ [[draw textext.drt("\setfontid%i\relax\char%i\relax") shifted (%N,%N);]] ] --- local f_rule = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ] --- --- local current = nil --- local size = 0 --- --- function mp.place_buffermake(box) --- drivers.convert("mps",box) --- current = drivers.action("mps","fetch") --- size = #current --- end --- --- function mp.place_buffersize() --- mpprint(size) --- end --- --- function mp.place_bufferslot(i) --- if i > 0 and i <= size then --- local b = buffer[i] --- local t = b[1] --- if t == "glyph" then --- mpprint(f_glyph(b[2],b[3],b[4]*bpfactor,b[5]*bpfactor)) --- elseif t == "rule" then --- mpprint(f_rule(b[2]*bpfactor,b[3]*bpfactor,b[4]*bpfactor,b[5]*bpfactor)) --- end --- end --- end --- --- function mp.place_bufferwipe() --- current = nil --- size = 0 --- end diff --git a/tex/context/base/mkiv/back-mps.mkxl b/tex/context/base/mkiv/back-mps.mkxl index 0a6640614..318b73848 100644 --- a/tex/context/base/mkiv/back-mps.mkxl +++ b/tex/context/base/mkiv/back-mps.mkxl @@ -12,7 +12,7 @@ %C details. \ifcase\contextlmtxmode \else - \registerctxluafile{back-mps}{optimize} + \registerctxluafile{back-mps}{autosuffix,optimize} \fi \endinput diff --git a/tex/context/base/mkiv/back-out.lmt b/tex/context/base/mkiv/back-out.lmt new file mode 100644 index 000000000..5ea5aa048 --- /dev/null +++ b/tex/context/base/mkiv/back-out.lmt @@ -0,0 +1,259 @@ +if not modules then modules = { } end modules ['back-out'] = { + version = 1.001, + comment = "companion to back-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type = type +local loadstring = loadstring + +local context = context + +-- tokens.scanners..... + +local get = token.get_index +local scaninteger = token.scan_int +local scanstring = token.scan_string +local scankeyword = token.scan_keyword +local scantokenlist = token.scan_tokenlist +----- scancode = token.scan_code + +local tokentostring = token.to_string + +local logwriter = logs.writer +local openfile = io.open +local flushio = io.flush + +local nuts = nodes.nuts +local tonode = nuts.tonode +local copynode = nuts.copy +local nodepool = nuts.pool + +local getdata = nuts.getdata + +local whatsit_code = nodes.nodecodes.whatsit + +local whatsitcodes = nodes.whatsitcodes + +local literalvalues = nodes.literalvalues +local originliteral_code = literalvalues.origin +local pageliteral_code = literalvalues.page +local directliteral_code = literalvalues.direct +local rawliteral_code = literalvalues.raw + +local nodeproperties = nodes.properties.data + +local channels = { } + +local register = nodepool.register +local newnut = nuts.new + +local opennode = register(newnut(whatsit_code,whatsitcodes.open)) +local writenode = register(newnut(whatsit_code,whatsitcodes.write)) +local closenode = register(newnut(whatsit_code,whatsitcodes.close)) +local lateluanode = register(newnut(whatsit_code,whatsitcodes.latelua)) +local literalnode = register(newnut(whatsit_code,whatsitcodes.literal)) +local savenode = register(newnut(whatsit_code,whatsitcodes.save)) +local restorenode = register(newnut(whatsit_code,whatsitcodes.restore)) +local setmatrixnode = register(newnut(whatsit_code,whatsitcodes.setmatrix)) + +local tomatrix = drivers.helpers.tomatrix + +local immediately = false -- not watertight + +local open_command, write_command, close_command + +backends = backends or { } + +local function openout() + local channel = scaninteger() + scankeyword("=") -- hack + local filename = scanstring() + if not immediately then + local n = copynode(opennode) + nodeproperties[n] = { channel = channel, filename = filename } -- action = "open" + return context(tonode(n)) + elseif not channels[channel] then + local handle = openfile(filename,"wb") or false + if handle then + channels[channel] = handle + else + -- error + end + end + immediately = false +end + +function backends.openout(n) + local p = nodeproperties[n] + if p then + local handle = openfile(p.filename,"wb") or false + if handle then + channels[p.channel] = handle + else + -- error + end + end +end + +local function write() + local channel = scaninteger() + if not immediately then + local t = scantokenlist() + local n = copynode(writenode) + nodeproperties[n] = { channel = channel, data = t } -- action = "write" + return context(tonode(n)) + else + local content = scanstring() + local handle = channels[channel] + if handle then + handle:write(content,"\n") + else + logwriter(content,"\n") + end + end + immediately = false +end + +function backends.writeout(n) + local p = nodeproperties[n] + if p then + local handle = channels[p.channel] + local content = tokentostring(p.data) + if handle then + handle:write(content,"\n") + else + logwriter(content,"\n") + end + end +end + +local function closeout() + local channel = scaninteger() + if not immediately then + local n = copynode(closenode) + nodeproperties[n] = { channel = channel } -- action = "close" + return context(tonode(n)) + else + local handle = channels[channel] + if handle then + handle:close() + channels[channel] = false + flushio() + else + -- error + end + end + immediately = false +end + +function backends.closeout(n) + local p = nodeproperties[n] + if p then + local channel = p.channel + local handle = channels[channel] + if handle then + handle:close() + channels[channel] = false + flushio() + else + -- error + end + end +end + +local function immediate() + immediately = true +end + +local noflatelua = 0 + +local function latelua() + local node = copynode(lateluanode) + local name = "latelua" + if scankeyword("name") then + name = scanstring() + end + local data = scantokenlist() + nodeproperties[node] = { name = name, data = data } + return context(tonode(node)) +end + +function backends.latelua(current,pos_h,pos_v) -- todo: pass pos_h and pos_v (more efficient in lmtx) + local p = nodeproperties[current] + if p then + data = p.data + else + data = getdata(current) + end + noflatelua = noflatelua + 1 + local kind = type(data) + if kind == "table" then + data.action(data.specification or data) + elseif kind == "function" then + data() + else + if kind ~= "string" then + data = tokentostring(data) + end + if #data ~= "" then + local code = loadstring(data) + if code then + code() + end + end + end +end + +function backends.noflatelua() + return noflatelua +end + +function nodepool.originliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = originliteral_code } return t end +function nodepool.pageliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = pageliteral_code } return t end +function nodepool.directliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = directliteral_code } return t end +function nodepool.rawliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = rawliteral_code } return t end + +local pdfliterals = { + [originliteral_code] = originliteral_code, [literalvalues[originliteral_code]] = originliteral_code, + [pageliteral_code] = pageliteral_code, [literalvalues[pageliteral_code]] = pageliteral_code, + [directliteral_code] = directliteral_code, [literalvalues[directliteral_code]] = directliteral_code, + [rawliteral_code] = rawliteral_code, [literalvalues[rawliteral_code]] = rawliteral_code, +} + +function nodepool.literal(mode,str) + local t = copynode(literalnode) + if str then + nodeproperties[t] = { data = str, mode = pdfliterals[mode] or pageliteral_code } + else + nodeproperties[t] = { data = mode, mode = pageliteral_code } + end + return t +end + +function nodepool.save() + return copynode(savenode) +end + +function nodepool.restore() + return copynode(restorenode) +end + +function nodepool.setmatrix(rx,sx,sy,ry,tx,ty) + local t = copynode(setmatrixnode) + nodeproperties[t] = { matrix = tomatrix(rx,sx,sy,ry,tx,ty) } + return t +end + +interfaces.implement { name = "immediate", actions = immediate, public = true, protected = true } +interfaces.implement { name = "openout", actions = openout, public = true, protected = true } +interfaces.implement { name = "write", actions = write, public = true, protected = true } +interfaces.implement { name = "closeout", actions = closeout, public = true, protected = true } +interfaces.implement { name = "latelua", actions = latelua, public = true, protected = true } +interfaces.implement { name = "special", actions = scanstring, public = true, protected = true } + +open_command = get(token.create("openout")) +write_command = get(token.create("write")) +close_command = get(token.create("closeout")) diff --git a/tex/context/base/mkiv/back-out.lua b/tex/context/base/mkiv/back-out.lua deleted file mode 100644 index 5ea5aa048..000000000 --- a/tex/context/base/mkiv/back-out.lua +++ /dev/null @@ -1,259 +0,0 @@ -if not modules then modules = { } end modules ['back-out'] = { - version = 1.001, - comment = "companion to back-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local type = type -local loadstring = loadstring - -local context = context - --- tokens.scanners..... - -local get = token.get_index -local scaninteger = token.scan_int -local scanstring = token.scan_string -local scankeyword = token.scan_keyword -local scantokenlist = token.scan_tokenlist ------ scancode = token.scan_code - -local tokentostring = token.to_string - -local logwriter = logs.writer -local openfile = io.open -local flushio = io.flush - -local nuts = nodes.nuts -local tonode = nuts.tonode -local copynode = nuts.copy -local nodepool = nuts.pool - -local getdata = nuts.getdata - -local whatsit_code = nodes.nodecodes.whatsit - -local whatsitcodes = nodes.whatsitcodes - -local literalvalues = nodes.literalvalues -local originliteral_code = literalvalues.origin -local pageliteral_code = literalvalues.page -local directliteral_code = literalvalues.direct -local rawliteral_code = literalvalues.raw - -local nodeproperties = nodes.properties.data - -local channels = { } - -local register = nodepool.register -local newnut = nuts.new - -local opennode = register(newnut(whatsit_code,whatsitcodes.open)) -local writenode = register(newnut(whatsit_code,whatsitcodes.write)) -local closenode = register(newnut(whatsit_code,whatsitcodes.close)) -local lateluanode = register(newnut(whatsit_code,whatsitcodes.latelua)) -local literalnode = register(newnut(whatsit_code,whatsitcodes.literal)) -local savenode = register(newnut(whatsit_code,whatsitcodes.save)) -local restorenode = register(newnut(whatsit_code,whatsitcodes.restore)) -local setmatrixnode = register(newnut(whatsit_code,whatsitcodes.setmatrix)) - -local tomatrix = drivers.helpers.tomatrix - -local immediately = false -- not watertight - -local open_command, write_command, close_command - -backends = backends or { } - -local function openout() - local channel = scaninteger() - scankeyword("=") -- hack - local filename = scanstring() - if not immediately then - local n = copynode(opennode) - nodeproperties[n] = { channel = channel, filename = filename } -- action = "open" - return context(tonode(n)) - elseif not channels[channel] then - local handle = openfile(filename,"wb") or false - if handle then - channels[channel] = handle - else - -- error - end - end - immediately = false -end - -function backends.openout(n) - local p = nodeproperties[n] - if p then - local handle = openfile(p.filename,"wb") or false - if handle then - channels[p.channel] = handle - else - -- error - end - end -end - -local function write() - local channel = scaninteger() - if not immediately then - local t = scantokenlist() - local n = copynode(writenode) - nodeproperties[n] = { channel = channel, data = t } -- action = "write" - return context(tonode(n)) - else - local content = scanstring() - local handle = channels[channel] - if handle then - handle:write(content,"\n") - else - logwriter(content,"\n") - end - end - immediately = false -end - -function backends.writeout(n) - local p = nodeproperties[n] - if p then - local handle = channels[p.channel] - local content = tokentostring(p.data) - if handle then - handle:write(content,"\n") - else - logwriter(content,"\n") - end - end -end - -local function closeout() - local channel = scaninteger() - if not immediately then - local n = copynode(closenode) - nodeproperties[n] = { channel = channel } -- action = "close" - return context(tonode(n)) - else - local handle = channels[channel] - if handle then - handle:close() - channels[channel] = false - flushio() - else - -- error - end - end - immediately = false -end - -function backends.closeout(n) - local p = nodeproperties[n] - if p then - local channel = p.channel - local handle = channels[channel] - if handle then - handle:close() - channels[channel] = false - flushio() - else - -- error - end - end -end - -local function immediate() - immediately = true -end - -local noflatelua = 0 - -local function latelua() - local node = copynode(lateluanode) - local name = "latelua" - if scankeyword("name") then - name = scanstring() - end - local data = scantokenlist() - nodeproperties[node] = { name = name, data = data } - return context(tonode(node)) -end - -function backends.latelua(current,pos_h,pos_v) -- todo: pass pos_h and pos_v (more efficient in lmtx) - local p = nodeproperties[current] - if p then - data = p.data - else - data = getdata(current) - end - noflatelua = noflatelua + 1 - local kind = type(data) - if kind == "table" then - data.action(data.specification or data) - elseif kind == "function" then - data() - else - if kind ~= "string" then - data = tokentostring(data) - end - if #data ~= "" then - local code = loadstring(data) - if code then - code() - end - end - end -end - -function backends.noflatelua() - return noflatelua -end - -function nodepool.originliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = originliteral_code } return t end -function nodepool.pageliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = pageliteral_code } return t end -function nodepool.directliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = directliteral_code } return t end -function nodepool.rawliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = rawliteral_code } return t end - -local pdfliterals = { - [originliteral_code] = originliteral_code, [literalvalues[originliteral_code]] = originliteral_code, - [pageliteral_code] = pageliteral_code, [literalvalues[pageliteral_code]] = pageliteral_code, - [directliteral_code] = directliteral_code, [literalvalues[directliteral_code]] = directliteral_code, - [rawliteral_code] = rawliteral_code, [literalvalues[rawliteral_code]] = rawliteral_code, -} - -function nodepool.literal(mode,str) - local t = copynode(literalnode) - if str then - nodeproperties[t] = { data = str, mode = pdfliterals[mode] or pageliteral_code } - else - nodeproperties[t] = { data = mode, mode = pageliteral_code } - end - return t -end - -function nodepool.save() - return copynode(savenode) -end - -function nodepool.restore() - return copynode(restorenode) -end - -function nodepool.setmatrix(rx,sx,sy,ry,tx,ty) - local t = copynode(setmatrixnode) - nodeproperties[t] = { matrix = tomatrix(rx,sx,sy,ry,tx,ty) } - return t -end - -interfaces.implement { name = "immediate", actions = immediate, public = true, protected = true } -interfaces.implement { name = "openout", actions = openout, public = true, protected = true } -interfaces.implement { name = "write", actions = write, public = true, protected = true } -interfaces.implement { name = "closeout", actions = closeout, public = true, protected = true } -interfaces.implement { name = "latelua", actions = latelua, public = true, protected = true } -interfaces.implement { name = "special", actions = scanstring, public = true, protected = true } - -open_command = get(token.create("openout")) -write_command = get(token.create("write")) -close_command = get(token.create("closeout")) diff --git a/tex/context/base/mkiv/back-out.mkxl b/tex/context/base/mkiv/back-out.mkxl index 26548a0a4..248622c54 100644 --- a/tex/context/base/mkiv/back-out.mkxl +++ b/tex/context/base/mkiv/back-out.mkxl @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\registerctxluafile{back-out}{} +\registerctxluafile{back-out}{autosuffix} \let\normalimmediate\immediate \let\normalopenout \openout diff --git a/tex/context/base/mkiv/back-pdf.mkiv b/tex/context/base/mkiv/back-pdf.mkiv index a1265e47a..a8b157019 100644 --- a/tex/context/base/mkiv/back-pdf.mkiv +++ b/tex/context/base/mkiv/back-pdf.mkiv @@ -21,6 +21,7 @@ \registerctxluafile{lpdf-nod}{} \registerctxluafile{lpdf-eng}{optimize} \registerctxluafile{lpdf-col}{} +\registerctxluafile{lpdf-vfc}{} \registerctxluafile{lpdf-xmp}{} \registerctxluafile{lpdf-ano}{} \registerctxluafile{lpdf-res}{} diff --git a/tex/context/base/mkiv/back-pdf.mkxl b/tex/context/base/mkiv/back-pdf.mkxl index f9bb23ac9..9c55654d0 100644 --- a/tex/context/base/mkiv/back-pdf.mkxl +++ b/tex/context/base/mkiv/back-pdf.mkxl @@ -18,9 +18,9 @@ \writestatus{loading}{ConTeXt Backend Macros / PDF} \registerctxluafile{lpdf-ini}{optimize} -\registerctxluafile{lpdf-lmt}{optimize} - +\registerctxluafile{lpdf-lmt}{autosuffix,optimize} \registerctxluafile{lpdf-col}{} +\registerctxluafile{lpdf-vfc}{autosuffix} \registerctxluafile{lpdf-xmp}{} \registerctxluafile{lpdf-ano}{} \registerctxluafile{lpdf-res}{} @@ -35,9 +35,9 @@ \registerctxluafile{lpdf-tag}{} \registerctxluafile{lpdf-fmt}{} \registerctxluafile{lpdf-pde}{} -\registerctxluafile{lpdf-img}{optimize} +\registerctxluafile{lpdf-img}{autosuffix,optimize} \registerctxluafile{lpdf-epa}{} -\registerctxluafile{lpdf-emb}{optimize} +\registerctxluafile{lpdf-emb}{autosuffix,optimize} \registerctxluafile{lpdf-fnt}{} \registerctxluafile{back-pdp}{} diff --git a/tex/context/base/mkiv/cldf-ini.mkiv b/tex/context/base/mkiv/cldf-ini.mkiv index 4ce48d7af..0ec2d408b 100644 --- a/tex/context/base/mkiv/cldf-ini.mkiv +++ b/tex/context/base/mkiv/cldf-ini.mkiv @@ -15,7 +15,7 @@ \newcount\trialtypesettingstate % gets aliased at the Lua end -\registerctxluafile{cldf-ini}{} +\registerctxluafile{cldf-ini}{autosuffix} %D With each new update of \MKIV\ we can join Within Temptation in singing: %D diff --git a/tex/context/base/mkiv/cldf-int.lmt b/tex/context/base/mkiv/cldf-int.lmt new file mode 100644 index 000000000..4f486221b --- /dev/null +++ b/tex/context/base/mkiv/cldf-int.lmt @@ -0,0 +1,252 @@ +if not modules then modules = { } end modules ['cldf-int'] = { + version = 1.001, + comment = "companion to cldf-int.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- another experiment +-- needs upgrading +-- needs checking +-- todo: multilingual + +local byte = string.byte +local insert, remove, concat = table.insert, table.remove, table.concat +local unpack, type = unpack or table.unpack, type + +local ctxcatcodes = catcodes.numbers.ctxcatcodes +local context = context +local contextsprint = context.sprint + +local trace_define = false trackers.register("context.define", function(v) trace_define = v end) + +interfaces = interfaces or { } +local implement = interfaces.implement +local estart = interfaces.elements.start +local estop = interfaces.elements.stop + +local scanners = tokens.scanners +local shortcuts = tokens.shortcuts + +local peekchar = scanners.peekchar +local scankey = scanners.key +local scanvalue = scanners.value +local scanskip = scanners.skip + +local open = byte('[') +local close = byte(']') +local equal = byte('=') +local comma = byte(',') + +function scanhash(scanners) + if peekchar() == open then + local data = { } + scanskip() + while true do + local c = peekchar() + if c == comma then + scanskip() + elseif c == close then + scanskip() + break + else + local key = scankey(equal) + if key then + if peekchar() == equal then + scanskip() + if scanners then + local scanner = scanners[key] + if scanner then + data[key] = scanner() + else + data[key] = scanvalue(comma,close) or "" + end + else + data[key] = scanvalue(comma,close) or "" + end + else + break + end + else + break + end + end + end + return data + end +end + +function scanarray() + if peekchar() == open then + local data = { } + local d = 0 + scanskip() + while true do + local c = peekchar() + if c == comma then + scanskip() + elseif c == close then + scanskip() + break + else + local v = scanvalue(comma,close) or "" + d = d + 1 + data[d] = v + end + end + return data + end +end + +shortcuts.scanhash = scanhash +shortcuts.scanarray = scanarray + +scanners.hash = scanhash +scanners.array = scanarray + +local function remap(arguments) + -- backward compatibility + if type(arguments) == "table" then + for i=1,#arguments do + local a = arguments[i] + if type(a) == "table" then + local t = a[2] + arguments[i] = t == "list" and "array" or t + end + end + return arguments + end +end + +function interfaces.definecommand(name,specification) -- name is optional + if type(name) == "table" then + specification = name + name = specification.name + end + if name and specification then + local environment = specification.environment + local arguments = remap(specification.arguments) + if environment then + local starter = specification.starter + local stopper = specification.stopper + if starter and stopper then + implement { + name = estart .. name, + arguments = arguments, + public = true, + protected = true, + actions = starter, + } + implement { + name = estop .. name, + public = true, + protected = true, + actions = stopper, + } + else + -- message + end + end + if not environment or environment == "both" then + local macro = specification.macro + if macro then + implement { + name = name, + arguments = arguments, + public = true, + protected = true, + actions = macro, + } + else + -- message + end + end + else + -- message + end +end + +function interfaces.tolist(t) + if t then + local r = { } + for i=1,#t do + r[i] = t[i] + end + local n = #r + for k,v in table.sortedhash(t) do + if type(k) ~= "number" then + n = n + 1 + r[n] = k .. "=" .. v + end + end + return concat(r,", ") + else + return "" + end +end + +-- \startluacode +-- function test(opt_1, opt_2, arg_1) +-- context.startnarrower() +-- context("options 1: %s",interfaces.tolist(opt_1)) +-- context.par() +-- context("options 2: %s",interfaces.tolist(opt_2)) +-- context.par() +-- context("argument 1: %s",arg_1) +-- context.stopnarrower() +-- end +-- +-- interfaces.definecommand { +-- name = "test", +-- arguments = { +-- { "option", "list" }, +-- { "option", "hash" }, +-- { "content", "string" }, +-- }, +-- macro = test, +-- } +-- \stopluacode +-- +-- test: \test[1][a=3]{whatever} +-- +-- \startluacode +-- local function startmore(opt_1) +-- context.startnarrower() +-- context("start more, options: %s",interfaces.tolist(opt_1)) +-- context.startnarrower() +-- end +-- +-- local function stopmore() +-- context.stopnarrower() +-- context("stop more") +-- context.stopnarrower() +-- end +-- +-- interfaces.definecommand ( "more", { +-- environment = true, +-- arguments = { +-- { "option", "list" }, +-- }, +-- starter = startmore, +-- stopper = stopmore, +-- } ) +-- \stopluacode +-- +-- more: \startmore[1] one \startmore[2] two \stopmore one \stopmore +-- +-- More modern (no need for option or content): +-- +-- \startluacode +-- interfaces.definecommand { +-- name = "test", +-- arguments = { +-- "array", -- or list +-- "hash", +-- "string", +-- "number", +-- }, +-- macro = test, +-- } +-- \stopluacode +-- diff --git a/tex/context/base/mkiv/cldf-int.lua b/tex/context/base/mkiv/cldf-int.lua index 47f825a4a..39a4eb335 100644 --- a/tex/context/base/mkiv/cldf-int.lua +++ b/tex/context/base/mkiv/cldf-int.lua @@ -1,315 +1,154 @@ if not modules then modules = { } end modules ['cldf-int'] = { version = 1.001, - comment = "companion to mult-clm.mkiv", + comment = "companion to cldf-int.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } --- another experiment --- needs upgrading --- needs checking --- todo: multilingual +-- another experiment, won't change etc ... mkiv stuff .. used? -local format, byte = string.format, string.byte local insert, remove, concat = table.insert, table.remove, table.concat local unpack, type = unpack or table.unpack, type -local catcodenumbers = catcodes.numbers - -local ctxcatcodes = catcodenumbers.ctxcatcodes -local vrbcatcodes = catcodenumbers.vrbcatcodes - +local ctxcatcodes = catcodes.numbers.ctxcatcodes local context = context local contextsprint = context.sprint local trace_define = false trackers.register("context.define", function(v) trace_define = v end) interfaces = interfaces or { } -local implement = interfaces.implement local estart = interfaces.elements.start local estop = interfaces.elements.stop -if CONTEXTLMTXMODE > 0 then +_clmh_ = utilities.parsers.settings_to_hash +_clma_ = utilities.parsers.settings_to_array +_clmn_ = tonumber - local scanners = tokens.scanners - local shortcuts = tokens.shortcuts +local starters, stoppers, macros, stack = { }, { }, { }, { } - local peekchar = scanners.peekchar - local scankey = scanners.key - local scanvalue = scanners.value - local scanskip = scanners.skip +local checkers = { + [0] = "", + "\\dosingleempty", + "\\dodoubleempty", + "\\dotripleempty", + "\\doquadrupleempty", + "\\doquintupleempty", + "\\dosixtupleempty", +} - local open = byte('[') - local close = byte(']') - local equal = byte('=') - local comma = byte(',') +function _clmm_(name,...) + macros[name](...) +end - function scanhash(scanners) - if peekchar() == open then - local data = { } - scanskip() - while true do - local c = peekchar() - if c == comma then - scanskip() - elseif c == close then - scanskip() - break - else - local key = scankey(equal) - if key then - if peekchar() == equal then - scanskip() - if scanners then - local scanner = scanners[key] - if scanner then - data[key] = scanner() - else - data[key] = scanvalue(comma,close) or "" - end - else - data[key] = scanvalue(comma,close) or "" - end - else - break - end - else - break - end - end - end - return data - end - end +function _clmb_(name,...) + local sn = stack[name] + insert(sn,{...}) + starters[name](...) +end - function scanarray() - if peekchar() == open then - local data = { } - local d = 0 - scanskip() - while true do - local c = peekchar() - if c == comma then - scanskip() - elseif c == close then - scanskip() - break - else - local v = scanvalue(comma,close) or "" - d = d + 1 - data[d] = v - end - end - return data - end +function _clme_(name) + local sn = stack[name] + local sv = remove(sn) + if sv then + stoppers[name](unpack(sv)) + else + -- nesting error end +end - shortcuts.scanhash = scanhash - shortcuts.scanarray = scanarray - - scanners.hash = scanhash - scanners.array = scanarray +-- this is a bit old definition ... needs to be modernized - local function remap(arguments) - -- backward compatibility - if type(arguments) == "table" then - for i=1,#arguments do - local a = arguments[i] - if type(a) == "table" then - local t = a[2] - arguments[i] = t == "list" and "array" or t - end - end - return arguments - end +function interfaces.definecommand(name,specification) -- name is optional + if type(name) == "table" then + specification = name + name = specification.name end - - function interfaces.definecommand(name,specification) -- name is optional - if type(name) == "table" then - specification = name - name = specification.name - end - if name and specification then - local environment = specification.environment - local arguments = remap(specification.arguments) + if name and specification then + local arguments = specification.arguments + local na = (arguments and #arguments) or 0 + local environment = specification.environment + if na == 0 then if environment then - local starter = specification.starter - local stopper = specification.stopper - if starter and stopper then - implement { - name = estart .. name, - arguments = arguments, - public = true, - protected = true, - actions = starter, - } - implement { - name = estop .. name, - public = true, - protected = true, - actions = stopper, - } - else - -- message - end + contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{\\ctxlua{_clmb_('",name,"')}}") + contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}") end if not environment or environment == "both" then - local macro = specification.macro - if macro then - implement { - name = name, - arguments = arguments, - public = true, - protected = true, - actions = macro, - } - else - -- message - end + contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{\\ctxlua{_clmm_('",name,"')}}") end else - -- message - end - end - - -else - - _clmh_ = utilities.parsers.settings_to_hash - _clma_ = utilities.parsers.settings_to_array - - local starters, stoppers, macros, stack = { }, { }, { }, { } - - local checkers = { - [0] = "", - "\\dosingleempty", - "\\dodoubleempty", - "\\dotripleempty", - "\\doquadrupleempty", - "\\doquintupleempty", - "\\dosixtupleempty", - } - - function _clmm_(name,...) - macros[name](...) - end - - function _clmb_(name,...) - local sn = stack[name] - insert(sn,{...}) - starters[name](...) - end - - function _clme_(name) - local sn = stack[name] - local sv = remove(sn) - if sv then - stoppers[name](unpack(sv)) - else - -- nesting error - end - end - - _clmn_ = tonumber - - local estart = interfaces.elements.start - local estop = interfaces.elements.stop - - -- this is a bit old definition ... needs to be modernized - - function interfaces.definecommand(name,specification) -- name is optional - if type(name) == "table" then - specification = name - name = specification.name - end - if name and specification then - local arguments = specification.arguments - local na = (arguments and #arguments) or 0 - local environment = specification.environment - if na == 0 then - if environment then - contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{\\ctxlua{_clmb_('",name,"')}}") - contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}") - end - if not environment or environment == "both" then - contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{\\ctxlua{_clmm_('",name,"')}}") - end - else - -- we could flush immediate but tracing is bad then - stack[name] = { } - local opt = 0 - local done = false - local snippets = { } -- we can reuse it - local mkivdo = "\\mkivdo" .. name -- maybe clddo - snippets[#snippets+1] = "\\def" - snippets[#snippets+1] = mkivdo - for i=1,na do - local a = arguments[i] - local variant = a[1] - if variant == "option" then - snippets[#snippets+1] = "[#" - snippets[#snippets+1] = i - snippets[#snippets+1] = "]" - if not done then - opt = opt + 1 - end - else - done = true -- no more optional checking after this - snippets[#snippets+1] = "#" - snippets[#snippets+1] = i + -- we could flush immediate but tracing is bad then + stack[name] = { } + local opt = 0 + local done = false + local snippets = { } -- we can reuse it + local mkivdo = "\\mkivdo" .. name -- maybe clddo + snippets[#snippets+1] = "\\def" + snippets[#snippets+1] = mkivdo + for i=1,na do + local a = arguments[i] + local variant = a[1] + if variant == "option" then + snippets[#snippets+1] = "[#" + snippets[#snippets+1] = i + snippets[#snippets+1] = "]" + if not done then + opt = opt + 1 end - end - if environment then - snippets[#snippets+1] = "{\\ctxlua{_clmb_('" - snippets[#snippets+1] = name - snippets[#snippets+1] = "'" else - snippets[#snippets+1] = "{\\ctxlua{_clmm_('" - snippets[#snippets+1] = name - snippets[#snippets+1] = "'" - end - for i=1,na do - local a = arguments[i] - local variant = a[2] - if variant == "list" then - snippets[#snippets+1] = ",_clma_([==[#" - snippets[#snippets+1] = i - snippets[#snippets+1] = "]==])" - elseif variant == "hash" then - snippets[#snippets+1] = ",_clmh_([==[#" - snippets[#snippets+1] = i - snippets[#snippets+1] = "]==])" - elseif variant == "number" then - snippets[#snippets+1] = ",_clmn_([==[#" - snippets[#snippets+1] = i - snippets[#snippets+1] = "]==])" - else - snippets[#snippets+1] = ",[==[#" - snippets[#snippets+1] = i - snippets[#snippets+1] = "]==]" - end - end - snippets[#snippets+1] = ")}}" - contextsprint(ctxcatcodes,unpack(snippets)) - if environment then - -- needs checking - contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{",checkers[opt],mkivdo,"}") - contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}") - end - if not environment or environment == "both" then - contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{",checkers[opt],mkivdo,"}") + done = true -- no more optional checking after this + snippets[#snippets+1] = "#" + snippets[#snippets+1] = i end end if environment then - starters[name] = specification.starter - stoppers[name] = specification.stopper + snippets[#snippets+1] = "{\\ctxlua{_clmb_('" + snippets[#snippets+1] = name + snippets[#snippets+1] = "'" else - macros[name] = specification.macro + snippets[#snippets+1] = "{\\ctxlua{_clmm_('" + snippets[#snippets+1] = name + snippets[#snippets+1] = "'" end + for i=1,na do + local a = arguments[i] + local variant = a[2] + if variant == "list" then + snippets[#snippets+1] = ",_clma_([==[#" + snippets[#snippets+1] = i + snippets[#snippets+1] = "]==])" + elseif variant == "hash" then + snippets[#snippets+1] = ",_clmh_([==[#" + snippets[#snippets+1] = i + snippets[#snippets+1] = "]==])" + elseif variant == "number" then + snippets[#snippets+1] = ",_clmn_([==[#" + snippets[#snippets+1] = i + snippets[#snippets+1] = "]==])" + else + snippets[#snippets+1] = ",[==[#" + snippets[#snippets+1] = i + snippets[#snippets+1] = "]==]" + end + end + snippets[#snippets+1] = ")}}" + contextsprint(ctxcatcodes,unpack(snippets)) + if environment then + -- needs checking + contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{",checkers[opt],mkivdo,"}") + contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}") + end + if not environment or environment == "both" then + contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{",checkers[opt],mkivdo,"}") + end + end + if environment then + starters[name] = specification.starter + stoppers[name] = specification.stopper + else + macros[name] = specification.macro end end - end function interfaces.tolist(t) diff --git a/tex/context/base/mkiv/cldf-int.mkxl b/tex/context/base/mkiv/cldf-int.mkxl index aae7d0416..603c22afc 100644 --- a/tex/context/base/mkiv/cldf-int.mkxl +++ b/tex/context/base/mkiv/cldf-int.mkxl @@ -13,7 +13,7 @@ \writestatus{loading}{ConTeXt Multilingual Macros / Lua} -\registerctxluafile{cldf-int}{} +\registerctxluafile{cldf-int}{autosuffix} \unprotect diff --git a/tex/context/base/mkiv/cldf-lmt.lmt b/tex/context/base/mkiv/cldf-lmt.lmt new file mode 100644 index 000000000..b23ab1bd0 --- /dev/null +++ b/tex/context/base/mkiv/cldf-lmt.lmt @@ -0,0 +1,720 @@ +if not modules then modules = { } end modules ['cldf-lmt'] = { + version = 1.001, + comment = "companion to toks-scn.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local next, load = next, load + +local setmetatableindex = table.setmetatableindex +local setmetatablenewindex = table.setmetatablenewindex +local serialize = table.serialize + +local random = math.random +local randomseed = math.randomseed +local round = math.round +local abs = math.abs + +local implement = interfaces.implement + +local scanners = tokens.scanners +local scanword = scanners.word +local scanstring = scanners.string +local scanboolean = scanners.boolean +local scandimen = scanners.dimen +local scanfloat = scanners.float +local scaninteger = scanners.integer +local scannumber = scanners.luanumber +local scanluainteger = scanners.luainteger +local scanluacardinal = scanners.luacardinal +local scanluanumber = scanners.luanumber +local scanargument = scanners.argument +local scantoken = scanners.token +local scancsname = scanners.csname + +local getindex = token.get_index + +local texsetdimen = tex.setdimen +local texget = tex.get + +local values = tokens.values +local none_code = values.none +local integer_code = values.integer +local cardinal_code = values.cardinal +local dimension_code = values.dimension +local skip_code = values.skip +local boolean_code = values.boolean +local float_code = values.float + +local context = context + +-- variables -- + +local floats = { } +local integers = { } +local cardinals = { } +local numbers = { } + +implement { + name = "luafloat", + public = true, + value = true, + actions = function(b) + local n = scanword() + if b == "value" then + context("%.99g",floats[n] or 0) + else + floats[n] = scanluanumber(true) + -- floats[n] = scanfloat(true) + end + end, +} + +implement { + name = "luainteger", + public = true, + value = true, + actions = function(b) + local n = scanword() + if b == "value" then + context("%i",integers[n] or 0) + else + integers[n] = scanluainteger(true) + end + end, +} + +implement { + name = "luacount", + public = true, + value = true, + actions = function(b) + local n = scanword() + if b == "value" then + return integer_code, integers[n] or 0 + else + integers[n] = scaninteger(true) + end + end, +} + +implement { + name = "luadimen", + public = true, + value = true, + actions = function(b) + local n = scanword() + if b == "value" then + return dimension_code, integers[n] or 0 + else + integers[n] = scandimen(false,false,true) + end + end, +} + +implement { + name = "luacardinal", + public = true, + value = true, + actions = function(b) + local n = scanword() + if b == "value" then + context("%1.0f",cardinals[n] or 0) + else + cardinals[n] = scanluacardinal(true) + end + end, +} + +implement { + name = "luanumber", + public = true, + value = true, + actions = function(b) + local n = scanword() + if b == "value" then + context("%N",floats[n] or integers[n] or cardinals[n] or 0) -- maybe %N + else + -- floats[n] = scanfloat(true) + floats[n] = scanluanumber(true) + end + end, +} + +implement { + name = "luarandom", + public = true, + value = true, + actions = function(b) + if b == "value" then + return integer_code, random(scanluainteger(),scanluainteger()) + else + randomseed(scanluainteger(true)) + end + end, +} + +interfaces.floats = floats +interfaces.integers = integers +interfaces.cardinals = cardinals + +interfaces.numbers = table.setmetatableindex(function(t,k) + return floats[k] or integers[k] or cardinals[k] +end) + +-- arrays -- + +local arrays = { } + +interfaces.arrays = arrays + +local newindex = lua.newindex + +implement { + name = "newarray", + public = true, + protected = true, + arguments = { { + { "name", "string" }, + { "nx", "integer" }, + { "ny", "integer" }, + { "type", "string" }, + } }, + actions = function(t) + local name = t.name + if t.name then + local nx = t.nx + local ny = t.ny + local ty = t.type or "integer" + local df = nil + if ty == "integer" or ty == "float" or ty == "dimension" then + df = 0 + elseif ty == "boolean" then + df = false + else + ty = nil + end + if nx and ty ~= nil then + local data + if ny then + data = newindex(t.ny) + for i=1,ny do + data[i] = newindex(nx,df) + end + else + data = newindex(nx,df) + end + arrays[name] = data + data.nx = nx + data.ny = ny + data.type = ty + if ty == "integer" then + data.scanner = scaninteger + elseif ty == "boolean" then + data.scanner = scanboolean + elseif ty == "dimension" then + data.scanner = scandimen + elseif ty == "float" then + data.scanner = scanfloat + end + if ty == "integer" then + data.code = integer_code + elseif ty == "boolean" then + data.code = boolean_code + elseif ty == "dimension" then + data.code = dimension_code + elseif ty == "float" then + data.code = float_code + end + end + end + end, +} + +implement { + name = "arrayvalue", + public = true, + value = true, + actions = function(b) + local name = scanstring() + if name then + local a = arrays[name] + if a then + local nx = a.nx + local ny = a.ny + local d = a + if ny then + d = d[scaninteger()] + end + local x = scaninteger() + if b == "value" then + local code = a.code + if code == float_code then + context("%.99g",d[x]) + else + return code, d[x] + end + else + d[x] = a.scanner() + end + end + end + end, +} + +implement { + name = "arrayequals", + public = true, + value = true, + actions = function(b) + local name = scanstring() + if name then + local a = arrays[name] + if a then + local nx = a.nx + local ny = a.ny + local d = a + if ny then + d = d[scaninteger()] + end + local x = scaninteger() + if b == "value" then + return boolean_code, a.scanner() == d[x] + end + end + end + end, +} + +implement { + name = "arraycompare", + public = true, + value = true, + actions = function(b) + local name = scanstring() + if name then + local a = arrays[name] + if a then + local nx = a.nx + local ny = a.ny + local d = a + if ny then + d = d[scaninteger()] + end + local x = scaninteger() + if b == "value" then + local v = a.scanner() + local d = d[x] + if d < v then + return integer_code, 0 + elseif d == v then + return integer_code, 1 + else + return integer_code, 2 + end + end + end + end + end, +} + +implement { + name = "showarray", + public = true, + protected = true, + actions = function() + local name = scanstring() + if name then + inspect(arrays[name]) + end + end, +} + +-- expressions -- + +local cache = table.setmetatableindex(function(t,k) + local code = "return function() local n = interfaces.numbers local a = interfaces.arrays return " .. k .. " end" + code = loadstring(code) + if code then + code = code() + end + t[k] = code or false + return code +end) + +table.makeweak(cache) + +implement { + name = "luaexpression", + public = true, + actions = function() + local how = scanword() + local code = cache[scanargument()] + if code then + local result = code() + if result then + if not how then + context(tostring(code())) + elseif how == "float" then + context("%.99g",result) + elseif how == "integer" then + context("%i",round(result)) + elseif how == "cardinal" then + context("%d",abs(round(result))) + elseif how == "dimen" then + context("%p",result) + elseif how == "boolean" then + context("%d",result and 1 or 0) + elseif how == "lua" then + context("%q",result) + else + context(tostring(code())) + end + end + end + end +} + +local dimenfactors = number.dimenfactors + +implement { + name = "nodimen", + public = true, + value = true, + actions = function(b) + if b == "value" then + local how = scanword() + local what = scandimen() + if how then + local factor = dimenfactors[how] + if factor then + context("%.6N%s",factor*what,how) + else + return dimension_code, what + end + else + return dimension_code, what + end + else + local t = scantoken() + if t then + local i = getindex(t) + if i then + local d = scandimen(false,false,true) + texsetdimen(i,d) + end + end + end + end, +} + +-- experimental: + +local grouped = { } +local slots = { } +local nofslots = 0 +local nofgrouped = 0 + +local getdata = tokens.getdata +local setdata = tokens.setdata + +local report = logs.reporter("lua table") + +local ctxsprint = context.sprint + +-- we could have an extra one that collects all end of grouped actions +-- so that we dispose more in one go but it doesn's pay off + +local function newluatable(name,mt,dispose) + local g = { } + local t = slots[nofslots] + slots[nofslots] = false + nofslots = nofslots - 1 + if not t then + nofgrouped = nofgrouped + 1 + t = nofgrouped + end + if mt then + mt = getdata(name) + if mt then + mt = grouped[mt] + if mt then + setmetatableindex(g,mt) + end + end + end + grouped[t] = g + setdata(name,t) + -- This is the slow part. Doing this at the TeX end saved 10% runtime. I'll + -- think of something that we can set it at the Lua end. + if dispose then + ctxsprint("\\atendofgrouped{\\disposeluatable\\" .. name .. "}") + end +end + +local function disposeluatable(name) + local t = getdata(name) + local g = grouped[t] + if g then + grouped[t] = false + nofslots = nofslots + 1 + slots[nofslots] = t + end +end + +local function setluatable(name,kv) + local t = getdata(name) + local g = grouped[t] + if g and kv then + for k, v in next, kv do + g[k] = v + end + end +end + +local function getfromluatable(name,k) + local t = getdata(name) + local g = grouped[t] + if g then + local v = g[k] + if v then + context(v) + else + local n = tonumber(k) + if n then + local v = g[n] + if v then + context(v) + end + end + end + end +end + +local function idxfromluatable(name,k) + local t = getdata(name) + local g = grouped[t] + if g then + local v = g[k] + if v then + context(v) + end + end +end + +local function getluatable(name,k) + local t = getdata(name) + local g = grouped[t] + if g then + return g + end +end + +local function inspectluatable(name) + local t = getdata(name) + local g = grouped[t] + if g then + report("%s", serialize(g,'[grouped slot ' .. t .. ']')) + end +end + +local function showluatables() + report("nofgrouped %i, nofslots %i",nofgrouped,nofslots) + for t=1,nofgrouped do + local g = grouped[t] + if g then + report("%s", serialize(g,'[grouped slot ' .. t .. ']')) + end + end +end + +implement { + name = "newluatable", + protected = true, + -- public = true, + arguments = "csname", + actions = newluatable, +} + +implement { + name = "useluatable", + protected = true, + -- public = true, + arguments = { "csname", true }, + actions = newluatable, +} + +implement { + name = "disposeluatable", + protected = true, + public = true, + arguments = "csname", + actions = disposeluatable, +} + +implement { + name = "inspectluatable", + protected = true, + public = true, + arguments = "csname", + actions = inspectluatable, +} + +implement { + name = "showluatables", + protected = true, + public = true, + actions = showluatables, +} + +implement { + name = "setluatable", + protected = true, + public = true, + arguments = { "csname", "argument" }, + actions = function(name,data) + data = load("return {" .. data .. "}") + if data then + data = data() + if data then + setluatable(name,data) + end + end + end +} + +implement { + name = "getfromluatable", + protected = false, + public = true, + arguments = { "csname", "argument" }, + actions = getfromluatable, +} + +implement { + name = "idxfromluatable", + protected = false, + public = true, + arguments = { "csname", "integer" }, + actions = idxfromluatable, +} + +context.luatables = { + new = function(name) newluatable(name,false,true) end, + use = function(name) useluatable(name,true, true) end, + dispose = disposeluatable, + set = setluatable, + get = getluatable, + getfrom = getfromluatable, + idxfrom = idxfromluatable, + inspect = inspectluatable, + show = showluatables, +} + +-- Here's another mechanism ... + +local tables = { } +local stack = setmetatableindex("table") + +interfaces.implement { + name = "droptablegroup", + public = true, + actions = function() + local g = texget("currentgrouplevel") -- todo: tex.getgrouplevel() + local s = stack[g] + if s then + for t, data in next, s do + for k, v in next, data do + t[k] = v + end + end + stack[g] = { } + end + end, +} + +local ctx_atendofgroup = context.core.cs.atendofgroup +local ctx_droptablegroup = context.core.cs.droptablegroup + +local function handletable(t,b,array) + if b == "value" then + local k = array and scaninteger() or scanargument() + local v = t[k] + if v then + context(v) + end + else + local data = scanargument() + data = load("return {" .. data .. "}") + if data then + data = data() + if data then + local l = t.level + local g = texget("currentgrouplevel") -- todo: tex.getgrouplevel() + local s = stack[g] + local d = s[t] + if not d then + d = { } + s[t] = d + ctx_atendofgroup() + ctx_droptablegroup() + end + for k, v in next, data do + if not d[k] then + d[k] = t[k] + end + t[k] = v + end + if b == "global" then + for k, v in next, stack do + local t = s[t] + if t then + for k, v in next, data do + if t[k] then + t[k] = nil + end + end + end + end + end + end + end + end +end + +local function newtable(array) + local name = scancsname(true) + if not tables[name] then + local t = { } + tables[name] = t + interfaces.implement { + name = name, + public = true, + value = true, + actions = function(b) + handletable(t,b,array) + end, + } + else + -- already defined + end +end + +implement { + name = "newhashedtable", + protected = true, + public = true, + actions = newtable, +} + +implement { + name = "newindexedtable", + protected = true, + public = true, + actions = function() newtable(true) end, +} + +context.hashedtables = setmetatableindex(function(t,k) return tables[k] end) +context.indexedtables = context.hashedtables diff --git a/tex/context/base/mkiv/cldf-lmt.lua b/tex/context/base/mkiv/cldf-lmt.lua deleted file mode 100644 index b23ab1bd0..000000000 --- a/tex/context/base/mkiv/cldf-lmt.lua +++ /dev/null @@ -1,720 +0,0 @@ -if not modules then modules = { } end modules ['cldf-lmt'] = { - version = 1.001, - comment = "companion to toks-scn.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local next, load = next, load - -local setmetatableindex = table.setmetatableindex -local setmetatablenewindex = table.setmetatablenewindex -local serialize = table.serialize - -local random = math.random -local randomseed = math.randomseed -local round = math.round -local abs = math.abs - -local implement = interfaces.implement - -local scanners = tokens.scanners -local scanword = scanners.word -local scanstring = scanners.string -local scanboolean = scanners.boolean -local scandimen = scanners.dimen -local scanfloat = scanners.float -local scaninteger = scanners.integer -local scannumber = scanners.luanumber -local scanluainteger = scanners.luainteger -local scanluacardinal = scanners.luacardinal -local scanluanumber = scanners.luanumber -local scanargument = scanners.argument -local scantoken = scanners.token -local scancsname = scanners.csname - -local getindex = token.get_index - -local texsetdimen = tex.setdimen -local texget = tex.get - -local values = tokens.values -local none_code = values.none -local integer_code = values.integer -local cardinal_code = values.cardinal -local dimension_code = values.dimension -local skip_code = values.skip -local boolean_code = values.boolean -local float_code = values.float - -local context = context - --- variables -- - -local floats = { } -local integers = { } -local cardinals = { } -local numbers = { } - -implement { - name = "luafloat", - public = true, - value = true, - actions = function(b) - local n = scanword() - if b == "value" then - context("%.99g",floats[n] or 0) - else - floats[n] = scanluanumber(true) - -- floats[n] = scanfloat(true) - end - end, -} - -implement { - name = "luainteger", - public = true, - value = true, - actions = function(b) - local n = scanword() - if b == "value" then - context("%i",integers[n] or 0) - else - integers[n] = scanluainteger(true) - end - end, -} - -implement { - name = "luacount", - public = true, - value = true, - actions = function(b) - local n = scanword() - if b == "value" then - return integer_code, integers[n] or 0 - else - integers[n] = scaninteger(true) - end - end, -} - -implement { - name = "luadimen", - public = true, - value = true, - actions = function(b) - local n = scanword() - if b == "value" then - return dimension_code, integers[n] or 0 - else - integers[n] = scandimen(false,false,true) - end - end, -} - -implement { - name = "luacardinal", - public = true, - value = true, - actions = function(b) - local n = scanword() - if b == "value" then - context("%1.0f",cardinals[n] or 0) - else - cardinals[n] = scanluacardinal(true) - end - end, -} - -implement { - name = "luanumber", - public = true, - value = true, - actions = function(b) - local n = scanword() - if b == "value" then - context("%N",floats[n] or integers[n] or cardinals[n] or 0) -- maybe %N - else - -- floats[n] = scanfloat(true) - floats[n] = scanluanumber(true) - end - end, -} - -implement { - name = "luarandom", - public = true, - value = true, - actions = function(b) - if b == "value" then - return integer_code, random(scanluainteger(),scanluainteger()) - else - randomseed(scanluainteger(true)) - end - end, -} - -interfaces.floats = floats -interfaces.integers = integers -interfaces.cardinals = cardinals - -interfaces.numbers = table.setmetatableindex(function(t,k) - return floats[k] or integers[k] or cardinals[k] -end) - --- arrays -- - -local arrays = { } - -interfaces.arrays = arrays - -local newindex = lua.newindex - -implement { - name = "newarray", - public = true, - protected = true, - arguments = { { - { "name", "string" }, - { "nx", "integer" }, - { "ny", "integer" }, - { "type", "string" }, - } }, - actions = function(t) - local name = t.name - if t.name then - local nx = t.nx - local ny = t.ny - local ty = t.type or "integer" - local df = nil - if ty == "integer" or ty == "float" or ty == "dimension" then - df = 0 - elseif ty == "boolean" then - df = false - else - ty = nil - end - if nx and ty ~= nil then - local data - if ny then - data = newindex(t.ny) - for i=1,ny do - data[i] = newindex(nx,df) - end - else - data = newindex(nx,df) - end - arrays[name] = data - data.nx = nx - data.ny = ny - data.type = ty - if ty == "integer" then - data.scanner = scaninteger - elseif ty == "boolean" then - data.scanner = scanboolean - elseif ty == "dimension" then - data.scanner = scandimen - elseif ty == "float" then - data.scanner = scanfloat - end - if ty == "integer" then - data.code = integer_code - elseif ty == "boolean" then - data.code = boolean_code - elseif ty == "dimension" then - data.code = dimension_code - elseif ty == "float" then - data.code = float_code - end - end - end - end, -} - -implement { - name = "arrayvalue", - public = true, - value = true, - actions = function(b) - local name = scanstring() - if name then - local a = arrays[name] - if a then - local nx = a.nx - local ny = a.ny - local d = a - if ny then - d = d[scaninteger()] - end - local x = scaninteger() - if b == "value" then - local code = a.code - if code == float_code then - context("%.99g",d[x]) - else - return code, d[x] - end - else - d[x] = a.scanner() - end - end - end - end, -} - -implement { - name = "arrayequals", - public = true, - value = true, - actions = function(b) - local name = scanstring() - if name then - local a = arrays[name] - if a then - local nx = a.nx - local ny = a.ny - local d = a - if ny then - d = d[scaninteger()] - end - local x = scaninteger() - if b == "value" then - return boolean_code, a.scanner() == d[x] - end - end - end - end, -} - -implement { - name = "arraycompare", - public = true, - value = true, - actions = function(b) - local name = scanstring() - if name then - local a = arrays[name] - if a then - local nx = a.nx - local ny = a.ny - local d = a - if ny then - d = d[scaninteger()] - end - local x = scaninteger() - if b == "value" then - local v = a.scanner() - local d = d[x] - if d < v then - return integer_code, 0 - elseif d == v then - return integer_code, 1 - else - return integer_code, 2 - end - end - end - end - end, -} - -implement { - name = "showarray", - public = true, - protected = true, - actions = function() - local name = scanstring() - if name then - inspect(arrays[name]) - end - end, -} - --- expressions -- - -local cache = table.setmetatableindex(function(t,k) - local code = "return function() local n = interfaces.numbers local a = interfaces.arrays return " .. k .. " end" - code = loadstring(code) - if code then - code = code() - end - t[k] = code or false - return code -end) - -table.makeweak(cache) - -implement { - name = "luaexpression", - public = true, - actions = function() - local how = scanword() - local code = cache[scanargument()] - if code then - local result = code() - if result then - if not how then - context(tostring(code())) - elseif how == "float" then - context("%.99g",result) - elseif how == "integer" then - context("%i",round(result)) - elseif how == "cardinal" then - context("%d",abs(round(result))) - elseif how == "dimen" then - context("%p",result) - elseif how == "boolean" then - context("%d",result and 1 or 0) - elseif how == "lua" then - context("%q",result) - else - context(tostring(code())) - end - end - end - end -} - -local dimenfactors = number.dimenfactors - -implement { - name = "nodimen", - public = true, - value = true, - actions = function(b) - if b == "value" then - local how = scanword() - local what = scandimen() - if how then - local factor = dimenfactors[how] - if factor then - context("%.6N%s",factor*what,how) - else - return dimension_code, what - end - else - return dimension_code, what - end - else - local t = scantoken() - if t then - local i = getindex(t) - if i then - local d = scandimen(false,false,true) - texsetdimen(i,d) - end - end - end - end, -} - --- experimental: - -local grouped = { } -local slots = { } -local nofslots = 0 -local nofgrouped = 0 - -local getdata = tokens.getdata -local setdata = tokens.setdata - -local report = logs.reporter("lua table") - -local ctxsprint = context.sprint - --- we could have an extra one that collects all end of grouped actions --- so that we dispose more in one go but it doesn's pay off - -local function newluatable(name,mt,dispose) - local g = { } - local t = slots[nofslots] - slots[nofslots] = false - nofslots = nofslots - 1 - if not t then - nofgrouped = nofgrouped + 1 - t = nofgrouped - end - if mt then - mt = getdata(name) - if mt then - mt = grouped[mt] - if mt then - setmetatableindex(g,mt) - end - end - end - grouped[t] = g - setdata(name,t) - -- This is the slow part. Doing this at the TeX end saved 10% runtime. I'll - -- think of something that we can set it at the Lua end. - if dispose then - ctxsprint("\\atendofgrouped{\\disposeluatable\\" .. name .. "}") - end -end - -local function disposeluatable(name) - local t = getdata(name) - local g = grouped[t] - if g then - grouped[t] = false - nofslots = nofslots + 1 - slots[nofslots] = t - end -end - -local function setluatable(name,kv) - local t = getdata(name) - local g = grouped[t] - if g and kv then - for k, v in next, kv do - g[k] = v - end - end -end - -local function getfromluatable(name,k) - local t = getdata(name) - local g = grouped[t] - if g then - local v = g[k] - if v then - context(v) - else - local n = tonumber(k) - if n then - local v = g[n] - if v then - context(v) - end - end - end - end -end - -local function idxfromluatable(name,k) - local t = getdata(name) - local g = grouped[t] - if g then - local v = g[k] - if v then - context(v) - end - end -end - -local function getluatable(name,k) - local t = getdata(name) - local g = grouped[t] - if g then - return g - end -end - -local function inspectluatable(name) - local t = getdata(name) - local g = grouped[t] - if g then - report("%s", serialize(g,'[grouped slot ' .. t .. ']')) - end -end - -local function showluatables() - report("nofgrouped %i, nofslots %i",nofgrouped,nofslots) - for t=1,nofgrouped do - local g = grouped[t] - if g then - report("%s", serialize(g,'[grouped slot ' .. t .. ']')) - end - end -end - -implement { - name = "newluatable", - protected = true, - -- public = true, - arguments = "csname", - actions = newluatable, -} - -implement { - name = "useluatable", - protected = true, - -- public = true, - arguments = { "csname", true }, - actions = newluatable, -} - -implement { - name = "disposeluatable", - protected = true, - public = true, - arguments = "csname", - actions = disposeluatable, -} - -implement { - name = "inspectluatable", - protected = true, - public = true, - arguments = "csname", - actions = inspectluatable, -} - -implement { - name = "showluatables", - protected = true, - public = true, - actions = showluatables, -} - -implement { - name = "setluatable", - protected = true, - public = true, - arguments = { "csname", "argument" }, - actions = function(name,data) - data = load("return {" .. data .. "}") - if data then - data = data() - if data then - setluatable(name,data) - end - end - end -} - -implement { - name = "getfromluatable", - protected = false, - public = true, - arguments = { "csname", "argument" }, - actions = getfromluatable, -} - -implement { - name = "idxfromluatable", - protected = false, - public = true, - arguments = { "csname", "integer" }, - actions = idxfromluatable, -} - -context.luatables = { - new = function(name) newluatable(name,false,true) end, - use = function(name) useluatable(name,true, true) end, - dispose = disposeluatable, - set = setluatable, - get = getluatable, - getfrom = getfromluatable, - idxfrom = idxfromluatable, - inspect = inspectluatable, - show = showluatables, -} - --- Here's another mechanism ... - -local tables = { } -local stack = setmetatableindex("table") - -interfaces.implement { - name = "droptablegroup", - public = true, - actions = function() - local g = texget("currentgrouplevel") -- todo: tex.getgrouplevel() - local s = stack[g] - if s then - for t, data in next, s do - for k, v in next, data do - t[k] = v - end - end - stack[g] = { } - end - end, -} - -local ctx_atendofgroup = context.core.cs.atendofgroup -local ctx_droptablegroup = context.core.cs.droptablegroup - -local function handletable(t,b,array) - if b == "value" then - local k = array and scaninteger() or scanargument() - local v = t[k] - if v then - context(v) - end - else - local data = scanargument() - data = load("return {" .. data .. "}") - if data then - data = data() - if data then - local l = t.level - local g = texget("currentgrouplevel") -- todo: tex.getgrouplevel() - local s = stack[g] - local d = s[t] - if not d then - d = { } - s[t] = d - ctx_atendofgroup() - ctx_droptablegroup() - end - for k, v in next, data do - if not d[k] then - d[k] = t[k] - end - t[k] = v - end - if b == "global" then - for k, v in next, stack do - local t = s[t] - if t then - for k, v in next, data do - if t[k] then - t[k] = nil - end - end - end - end - end - end - end - end -end - -local function newtable(array) - local name = scancsname(true) - if not tables[name] then - local t = { } - tables[name] = t - interfaces.implement { - name = name, - public = true, - value = true, - actions = function(b) - handletable(t,b,array) - end, - } - else - -- already defined - end -end - -implement { - name = "newhashedtable", - protected = true, - public = true, - actions = newtable, -} - -implement { - name = "newindexedtable", - protected = true, - public = true, - actions = function() newtable(true) end, -} - -context.hashedtables = setmetatableindex(function(t,k) return tables[k] end) -context.indexedtables = context.hashedtables diff --git a/tex/context/base/mkiv/colo-ini.mkxl b/tex/context/base/mkiv/colo-ini.mkxl index 724316629..398465a8d 100644 --- a/tex/context/base/mkiv/colo-ini.mkxl +++ b/tex/context/base/mkiv/colo-ini.mkxl @@ -687,23 +687,17 @@ \else \colo_helpers_set_model\s!rgb \fi - \else - \ifconditional\c_colo_cmyk_supported - \colo_helpers_set_model\s!cmyk - \else - \ifconditional\c_colo_convert_gray - \colo_helpers_set_model\s!gray - \else - \colo_helpers_set_model\s!none - \fi - \fi - \fi - \else - \ifconditional\c_colo_convert_gray + \orelse\ifconditional\c_colo_cmyk_supported + \colo_helpers_set_model\s!cmyk + \orelse\ifconditional\c_colo_convert_gray \colo_helpers_set_model\s!gray \else \colo_helpers_set_model\s!none \fi + \orelse\ifconditional\c_colo_convert_gray + \colo_helpers_set_model\s!gray + \else + \colo_helpers_set_model\s!none \fi} %D Currently in mkiv transparency is implemented independent of color. This costs a @@ -846,9 +840,10 @@ {\advance\c_colo_protection\minusone} \def\colo_basics_define[#1][#2]% - {\edef\m_colo_old{#1}% - \edef\m_colo_new{#2}% - \ifx\m_colo_old\m_colo_new +% {\edef\m_colo_old{#1}% +% \edef\m_colo_new{#2}% +% \ifx\m_colo_old\m_colo_new + {\iftok{#1}{#2}% % maybe a warning \else \clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax @@ -859,9 +854,10 @@ \fi} \def\colo_basics_define_global[#1][#2]% - {\edef\m_colo_old{#1}% - \edef\m_colo_new{#2}% - \ifx\m_colo_old\m_colo_new +% {\edef\m_colo_old{#1}% +% \edef\m_colo_new{#2}% +% \ifx\m_colo_old\m_colo_new + {\iftok{#1}{#2}% % maybe a warning \else \clf_defineprocesscolorglobal{#1}{#2}\v_colo_freeze_state\relax @@ -1284,26 +1280,41 @@ \def\thecolorattribute #1{\number\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi} \def\thetransparencyattribute#1{\number\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi} -\def\internalspotcolorname #1{\clf_spotcolorname \thecolorattribute{#1} } -\def\internalspotcolorparent #1{\clf_spotcolorparent\thecolorattribute{#1} } -\def\internalspotcolorsize #1{\clf_spotcolorvalue \thecolorattribute{#1} } -\def\colorcomponents #1{\clf_colorcomponents \thecolorattribute {#1} } -\def\transparencycomponents #1{\clf_transparencycomponents\thetransparencyattribute{#1} } -\def\processcolorcomponents #1{\clf_processcolorcomponents\thecolorattribute {#1} } +% \def\internalspotcolorname #1{\clf_spotcolorname \thecolorattribute{#1} } +% \def\internalspotcolorparent #1{\clf_spotcolorparent\thecolorattribute{#1} } +% \def\internalspotcolorsize #1{\clf_spotcolorvalue \thecolorattribute{#1} } +% +% \def\colorcomponents #1{\clf_colorcomponents \thecolorattribute {#1} } +% \def\transparencycomponents #1{\clf_transparencycomponents\thetransparencyattribute{#1} } +% \def\processcolorcomponents #1{\clf_processcolorcomponents\thecolorattribute {#1} } +% +% \def\colorvalue #1{\clf_formatcolor\thecolorattribute{#1}{\colorformatseparator}} +% \def\grayvalue #1{\clf_formatgray \thecolorattribute{#1}{\colorformatseparator}} +% +% \def\doifelseblack #1{\clf_doifelseblack\thecolorattribute{#1} } +% \def\doifelsedrawingblack {\clf_doifelsedrawingblack} +% +% \let\doifblackelse \doifelseblack +% \let\doifdrawingblackelse \doifelsedrawingblack -\def\colorvalue #1{\clf_formatcolor\thecolorattribute{#1}{\colorformatseparator}} -\def\grayvalue #1{\clf_formatgray \thecolorattribute{#1}{\colorformatseparator}} +\def\internalspotcolorname #1{\clf_spotcolorname \rawcolorattribute{#1}} +\def\internalspotcolorparent #1{\clf_spotcolorparent\rawcolorattribute{#1}} +\def\internalspotcolorsize #1{\clf_spotcolorvalue \rawcolorattribute{#1}} -\def\doifelseblack #1{\clf_doifelseblack\thecolorattribute{#1} } +\def\colorcomponents #1{\clf_colorcomponents \rawcolorattribute {#1}} +\def\transparencycomponents #1{\clf_transparencycomponents\rawtransparencyattribute{#1}} +\def\processcolorcomponents #1{\clf_processcolorcomponents\rawcolorattribute {#1}} + +\def\colorvalue #1{\clf_formatcolor\rawcolorattribute{#1}{\colorformatseparator}} +\def\grayvalue #1{\clf_formatgray \rawcolorattribute{#1}{\colorformatseparator}} + +\def\doifelseblack #1{\clf_doifelseblack\rawcolorattribute{#1}} \def\doifelsedrawingblack {\clf_doifelsedrawingblack} \let\doifblackelse \doifelseblack \let\doifdrawingblackelse \doifelsedrawingblack -\let\doifblackelse \doifelseblack -\let\doifdrawingblackelse\doifelsedrawingblack - %D \macros %D {forcecolorhack} %D @@ -1328,7 +1339,7 @@ % % I really need to sort this out! -\unexpanded\def\forcecolorhack{\leaders\hrule height\zeropoint depth\zeropoint\hskip\zeropoint\relax} % relax is needed ! +\unexpanded\def\forcecolorhack{\leaders\hrule\s!height\zeropoint\s!depth\zeropoint\hskip\zeropoint\relax} % relax is needed ! %D We default to the colors defined in \type {colo-imp-rgb} and %D support both \RGB\ and \CMYK\ output. Transparencies are defined diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index dad7578d4..08aa956ca 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{2020.07.13 23:44} +\newcontextversion{2020.07.20 10:40} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 3ef78b28c..f7b67bb15 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{2020.07.13 23:44} +\edef\contextversion{2020.07.20 10:40} %D Kind of special: diff --git a/tex/context/base/mkiv/context.mkxl b/tex/context/base/mkiv/context.mkxl index 614c9a659..696be2dc8 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{2020.07.13 23:44} +\edef\contextversion{2020.07.20 10:40} %D Kind of special: diff --git a/tex/context/base/mkiv/core-env.lua b/tex/context/base/mkiv/core-env.lua index c496a5a8c..da10c26f5 100644 --- a/tex/context/base/mkiv/core-env.lua +++ b/tex/context/base/mkiv/core-env.lua @@ -100,27 +100,19 @@ setmetatableindex(texsystemmodes, function(t,k) end end end) + setmetatablenewindex(texsystemmodes, function(t,k) report_mode("you cannot set the %s named %a this way","systemmode",k) end) -setmetatableindex(texconstants, function(t,k) - return cache[k].mode ~= 0 and texgetcount(k) or 0 -end) setmetatablenewindex(texconstants, function(t,k) report_mode("you cannot set the %s named %a this way","constant",k) end) -setmetatableindex(texconditionals, function(t,k) -- 0 == true - return cache[k].mode ~= 0 and texgetcount(k) == 0 -end) setmetatablenewindex(texconditionals, function(t,k) report_mode("you cannot set the %s named %a this way","conditional",k) end) -table.setmetatableindex(texifs, function(t,k) - return cache[k].mode == iftrue -end) setmetatablenewindex(texifs, function(t,k) -- just ignore end) @@ -140,13 +132,27 @@ if CONTEXTLMTXMODE > 0 then return cache[k].command == countcode and texgetcount(k) == 0 end) - table.setmetatableindex(texifs, function(t,k) + setmetatableindex(texifs, function(t,k) local c = cache[k] print(k) inspect(c) return c.command == conditioncode and c.index == iftrue end) +else + + setmetatableindex(texconstants, function(t,k) + return cache[k].mode ~= 0 and texgetcount(k) or 0 + end) + + setmetatableindex(texconditionals, function(t,k) -- 0 == true + return cache[k].mode ~= 0 and texgetcount(k) == 0 + end) + + setmetatableindex(texifs, function(t,k) + return cache[k].mode == iftrue + end) + end tex.isdefined = isdefined diff --git a/tex/context/base/mkiv/core-lmt.lmt b/tex/context/base/mkiv/core-lmt.lmt new file mode 100644 index 000000000..700ce4721 --- /dev/null +++ b/tex/context/base/mkiv/core-lmt.lmt @@ -0,0 +1,34 @@ +if not modules then modules = { } end modules ['core-lmt'] = { + version = 1.001, + comment = "companion to core-lmt.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local implement = interfaces.implement +local scankeyword = tokens.scanners.keyword + +local settextdir = tex.settextdir +local setlinedir = tex.setlinedir +local setpardir = tex.setpardir +local setboxdir = tex.setboxdir + +local function scandir(what) + if scankeyword("tlt") then + what(0) + elseif scankeyword("trt") then + what(1) + -- elseif scankeyword("rtt") then + -- what(2) + -- elseif scankeyword("ltl") then + -- what(3) + else + what(0) + end +end + +implement { name = "textdir", public = true, protected = true, actions = function() scandir(settextdir) end } +implement { name = "linedir", public = true, protected = true, actions = function() scandir(setlinedir) end } +implement { name = "pardir", public = true, protected = true, actions = function() scandir(setpardir) end } +implement { name = "boxdir", public = true, protected = true, actions = function() scandir(setboxdir) end } diff --git a/tex/context/base/mkiv/core-lmt.lua b/tex/context/base/mkiv/core-lmt.lua deleted file mode 100644 index 700ce4721..000000000 --- a/tex/context/base/mkiv/core-lmt.lua +++ /dev/null @@ -1,34 +0,0 @@ -if not modules then modules = { } end modules ['core-lmt'] = { - version = 1.001, - comment = "companion to core-lmt.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local implement = interfaces.implement -local scankeyword = tokens.scanners.keyword - -local settextdir = tex.settextdir -local setlinedir = tex.setlinedir -local setpardir = tex.setpardir -local setboxdir = tex.setboxdir - -local function scandir(what) - if scankeyword("tlt") then - what(0) - elseif scankeyword("trt") then - what(1) - -- elseif scankeyword("rtt") then - -- what(2) - -- elseif scankeyword("ltl") then - -- what(3) - else - what(0) - end -end - -implement { name = "textdir", public = true, protected = true, actions = function() scandir(settextdir) end } -implement { name = "linedir", public = true, protected = true, actions = function() scandir(setlinedir) end } -implement { name = "pardir", public = true, protected = true, actions = function() scandir(setpardir) end } -implement { name = "boxdir", public = true, protected = true, actions = function() scandir(setboxdir) end } diff --git a/tex/context/base/mkiv/core-lmt.mkxl b/tex/context/base/mkiv/core-lmt.mkxl index 7fb38e830..77ef17966 100644 --- a/tex/context/base/mkiv/core-lmt.mkxl +++ b/tex/context/base/mkiv/core-lmt.mkxl @@ -13,7 +13,7 @@ \writestatus{loading}{ConTeXt System Macros / Primitives} -\registerctxluafile{core-lmt}{} +\registerctxluafile{core-lmt}{autosuffix} \unprotect diff --git a/tex/context/base/mkiv/driv-shp.lmt b/tex/context/base/mkiv/driv-shp.lmt new file mode 100644 index 000000000..2e9751b9c --- /dev/null +++ b/tex/context/base/mkiv/driv-shp.lmt @@ -0,0 +1,1361 @@ +if not modules then modules = { } end modules ['driv-shp'] = { + version = 1.001, + optimize = true, + comment = "companion to driv-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type, next = type, next +local round = math.round + +local setmetatableindex = table.setmetatableindex +local formatters = string.formatters +local concat = table.concat +local keys = table.keys +local sortedhash = table.sortedhash +local splitstring = string.split +local idiv = number.idiv +local extract = bit32.extract +local nuts = nodes.nuts + +local tonut = nodes.tonut +local tonode = nodes.tonode + +local getdirection = nuts.getdirection +local getlist = nuts.getlist +local getoffsets = nuts.getoffsets +local getorientation = nuts.getorientation +local getfield = nuts.getfield +local getwhd = nuts.getwhd +local getkern = nuts.getkern +local getheight = nuts.getheight +local getdepth = nuts.getdepth +----- getwidth = nuts.getwidth +local getnext = nuts.getnext +local getsubtype = nuts.getsubtype +local getid = nuts.getid +local getleader = nuts.getleader +----- getglue = nuts.getglue +local getshift = nuts.getshift +local getdata = nuts.getdata +----- getexpansion = nuts.getexpansion +local getreplace = nuts.getreplace +local setreplace = nuts.setreplace +local getfont = nuts.getfont + +local setdirection = nuts.setdirection +local setfield = nuts.setfield +local setlink = nuts.setlink + +local isglyph = nuts.isglyph +local findtail = nuts.tail +local nextdir = nuts.traversers.dir +local nextnode = nuts.traversers.node + +local rangedimensions = node.direct.rangedimensions -- nuts ? +local effectiveglue = nuts.effective_glue +local start_of_par = nuts.start_of_par +local dirdimensions = nuts.dirdimensions + +local texget = tex.get + +local fonthashes = fonts.hashes +local fontdata = fonthashes.identifiers +local characters = fonthashes.characters +local parameters = fonthashes.parameters + +local nodecodes = nodes.nodecodes +local whatsitcodes = nodes.whatsitcodes +local leadercodes = nodes.leadercodes +local gluecodes = nodes.gluecodes +local dircodes = nodes.dircodes +local dirvalues = nodes.dirvalues +local subtypes = nodes.subtypes + +local normaldir_code = dircodes.normal + +local lefttoright_code = dirvalues.lefttoright +local righttoleft_code = dirvalues.righttoleft + +local glyph_code = nodecodes.glyph +local kern_code = nodecodes.kern +local glue_code = nodecodes.glue +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local dir_code = nodecodes.dir +local disc_code = nodecodes.disc +local math_code = nodecodes.math +local rule_code = nodecodes.rule +local whatsit_code = nodecodes.whatsit +----- penalty_code = nodecodes.penalty +----- boundary_code = nodecodes.boundary + +local leaders_code = leadercodes.leaders +local cleaders_code = leadercodes.cleaders +local xleaders_code = leadercodes.xleaders +local gleaders_code = leadercodes.gleaders + +local spaceskip_code = gluecodes.spaceskip + +local saveposwhatsit_code = whatsitcodes.savepos +local userdefinedwhatsit_code = whatsitcodes.userdefined +local openwhatsit_code = whatsitcodes.open +local writewhatsit_code = whatsitcodes.write +local closewhatsit_code = whatsitcodes.close +local lateluawhatsit_code = whatsitcodes.latelua +local literalwhatsit_code = whatsitcodes.literal +local setmatrixwhatsit_code = whatsitcodes.setmatrix +local savewhatsit_code = whatsitcodes.save +local restorewhatsit_code = whatsitcodes.restore + +local getpagedimensions getpagedimensions = function() + getpagedimensions = backends.codeinjections.getpagedimensions + return getpagedimensions() +end + +local drivers = drivers +local instances = drivers.instances + +local report = logs.reporter("drivers") + +--------------------------------------------------------------------------------------- + +local lastfont = nil +local fontcharacters = nil + +local magicconstants = tex.magicconstants +local trueinch = magicconstants.trueinch +local maxdimen = magicconstants.maxdimen +local running = magicconstants.running + +local pos_h = 0 +local pos_v = 0 +local pos_r = lefttoright_code +local shippingmode = "none" + +local abs_max_v = 0 +local abs_max_h = 0 + +local shipbox_h = 0 +local shipbox_v = 0 +local page_size_h = 0 +local page_size_v = 0 +----- page_h_origin = 0 -- trueinch +----- page_v_origin = 0 -- trueinch + +local initialize +local finalize +local updatefontstate +local pushorientation +local poporientation +local flushcharacter +local flushfontchar +local flushrule +local flushliteral +local flushsetmatrix +local flushsave +local flushrestore +local flushspecial +----- flushimage + +-- make local + +function drivers.getpos () return round(pos_h), round(pos_v) end +function drivers.getrpos() return round(pos_h), round(pos_v), pos_r end +function drivers.gethpos() return round(pos_h) end +function drivers.getvpos() return round(pos_v) end + +-- characters + +local flush_character + +local stack = setmetatableindex("table") +local level = 0 +local nesting = 0 +local main = 0 + +-- experiment (smaller page stream but might be fragile) + +local tospace = false directives.register("backends.spaces", function(v) tospace = v end) + +-- todo: cache streams + +local default = 16384 * number.dimenfactors.bp -- 65536 // 4 + +local function flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommands) + + if nesting > 100 then + return + elseif nesting == 0 then + main = font + end + + nesting = nesting + 1 + + local saved_h = pos_h + local saved_v = pos_v + local saved_r = pos_r + pos_r = lefttoright_code + + local data = fontdata[font] + local fnt = font + local fonts = data.fonts + local siz = (data.parameters.factor or 1)/65536 + + local function flushchar(font,char,fnt,chr,f,e) + if fnt then + local nest = char ~= chr or font ~= fnt + if fnt == 0 then + fnt = main + end + return flush_character(false,fnt,chr,factor,nest,pos_h,pos_v,pos_r,f,e) + else + return 0 + end + end + + -- we assume resolved fonts: id mandate but maybe also size + + for i=1,#vfcommands do + local packet = vfcommands[i] + local command = packet[1] + if command == "char" then + local chr = packet[2] + local f = packet[3] + local e = packet[4] + pos_h = pos_h + flushchar(font,char,fnt,chr,f,e) + elseif command == "slot" then + local index = packet[2] + local chr = packet[3] + local f = packet[4] + local e = packet[5] + if index == 0 then + pos_h = pos_h + flushchar(font,char,font,chr,f,e) + else + local okay = fonts and fonts[index] + if okay then + local fnt = okay.id + if fnt then + pos_h = pos_h + flushchar(font,char,fnt,chr,f,e) + end + else + -- safeguard, we assume the font itself (often index 1) + pos_h = pos_h + flushchar(font,char,font,chr,f,e) + end + end + elseif command == "use" then + local index = packet[2] + if index then + local fnt + if index == 0 then + fnt = font + else + local okay = fonts and fonts[index] + if okay then + fnt = okay.id + end + end + if fnt then + -- not efficient but ok for now as experiment + local d = characters[fnt] + if d then + for i=3,#packet do + local chr = packet[i] + local dat = d[chr] + if dat then + flushfontchar(fnt,chr,dat) + end + end + end + end + end + elseif command == "right" then + local h = packet[2] * siz -- * siz is really needed for boldening + if factor ~= 0 and h ~= 0 then + h = h + h * factor / 1000 -- expansion + end + pos_h = pos_h + h + elseif command == "down" then + local v = packet[2] * siz -- * siz is really needed for boldening + pos_v = pos_v - v + elseif command == "push" then + level = level + 1 + local s = stack[level] + s[1] = pos_h + s[2] = pos_v + elseif command == "pop" then + if level > 0 then + local s = stack[level] + pos_h = s[1] + pos_v = s[2] + level = level - 1 + end + elseif command == "pdf" then + flushliteral(false,pos_h,pos_v,packet[2],packet[3]) + elseif command == "rule" then + local size_v = packet[2] + local size_h = packet[3] + if size_h > 0 and size_v > 0 then + if factor ~= 0 then + size_h = size_h + size_h * factor / 1000 + end + if size_h > 0 then + flushsimplerule(pos_h,pos_v,pos_r,size_h,size_v) + pos_h = pos_h + size_h + end + end + elseif command == "frame" then + local width = packet[2] + if width > 0 then + local height = packet[3] or 0 + local depth = packet[4] or 0 + local total = height + depth + if total > 0 then + if factor ~= 0 then + width = width + width * factor / 1000 + end + if width > 0 then + local line = packet[5] or default + local outline = not packet[6] + local advance = not packet[7] + flushspecialrule(pos_h,pos_v,pos_r,width,height,depth,line,outline) + if advance then + pos_h = pos_h + width + end + end + end + end + elseif command == "font" then + local index = packet[2] + local okay = fonts and fonts[index] + if okay then + fnt = okay.id or fnt -- or maybe just return + end + elseif command == "lua" then + local code = packet[2] + if type(code) ~= "function" then + code = loadstring(code) + end + if type(code) == "function" then + code(font,char,pos_h,pos_v) + end + elseif command == "node" then + local h = packet[2] + hlist_out(h,getlist(h)) + elseif command == "image" then + -- doesn't work because intercepted by engine so we use a different + -- mechanism (for now) + local image = packet[2] + -- to do + elseif command == "pdfmode" then + -- doesn't happen + -- elseif command == "special" then + -- -- not supported + -- elseif command == "nop" then + -- -- nothing to do| + -- elseif command == "scale" then + -- -- not supported + end + end + + pos_h = saved_h + pos_v = saved_v + pos_r = saved_r + + nesting = nesting - 1 +end + +local onetimemessage -- could be defined later (todo: make plug for this) + +flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r,f,e) + + if font ~= lastfont then + lastfont = font + fontcharacters = characters[font] + updatefontstate(font) + end + + local data = fontcharacters[char] + if not data then + if char > 0 then + if not onetimemessage then + onetimemessage = fonts.loggers.onetimemessage + end + onetimemessage(font,char,"missing") + end + return 0, 0, 0 + end + if vfcommands then + vfcommands = data.commands + end + local width, height, depth, naturalwidth + if current then + naturalwidth, height, depth, factor = getwhd(current,true) -- also get corrected width + if factor == 0 then + width = naturalwidth + else + -- width = (1.0 + factor/1000000.0) * naturalwidth + width = naturalwidth + naturalwidth * factor/1000000.0 + -- width = naturalwidth + naturalwidth * 0.000001 * factor + end + else + width = data.width or 0 + height = data.height or 0 + depth = data.depth or 0 + naturalwidth = width + if not factor then + factor = 0 + end + end + if pos_r == righttoleft_code then + pos_h = pos_h - width -- here ? + end + if vfcommands then + flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommands) -- also f ? + else + -- kind of messy that we do orientation here and offsets elsewhere + local orientation = data.orientation + if orientation and (orientation == 1 or orientation == 3) then + local x = data.xoffset + local y = data.yoffset + if x then + pos_h = pos_h + x + end + if y then + pos_v = pos_v + y + end + pushorientation(orientation,pos_h,pos_v) + flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) + poporientation(orientation,pos_h,pos_v) + else + flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) + end + end + return width, height, depth +end + +-- end of characters + +local function reset_state() + pos_h = 0 + pos_v = 0 + pos_r = lefttoright_code + shipbox_h = 0 + shipbox_v = 0 + shippingmode = "none" + page_size_h = 0 + page_size_v = 0 + -- page_h_origin = 0 -- trueinch + -- page_v_origin = 0 -- trueinch +end + +-- local function dirstackentry(t,k) +-- local v = { +-- cur_h = 0, +-- cur_v = 0, +-- ref_h = 0, +-- ref_v = 0, +-- } +-- t[k] = v +-- return v +-- end +-- +-- local dirstack = setmetatableindex(dirstackentry) +-- +-- local function reset_dir_stack() +-- dirstack = setmetatableindex(dirstackentry) +-- end + +local dirstack = { } + +local function reset_dir_stack() + dirstack = { } +end + +local leaderlevel = 0 + +local function flushlatelua(current,h,v) + -- Here we assume maganement by the lua function so currently we don't + -- check for leaderlevel. + return backends.latelua(current,h,v) +end + +local function flushwriteout(current) + if leaderlevel == 0 then + backends.writeout(current) + end +end + +local function flushopenout(current) + if leaderlevel == 0 then + backends.openout(current) + end +end + +local function flushcloseout(current) + if leaderlevel == 0 then + backends.closeout(current) + end +end + +local hlist_out, vlist_out do + + local function applyanchor(orientation,x,y,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) + local ot = extract(orientation, 0,4) + local ay = extract(orientation, 4,4) + local ax = extract(orientation, 8,4) + local of = extract(orientation,12,4) + if ot == 4 then + ot, ay = 0, 1 + elseif ot == 5 then + ot, ay = 0, 2 + end + if ot == 0 or ot == 2 then + if ax == 1 then x = x - width + elseif ax == 2 then x = x + width + elseif ax == 3 then x = x - width/2 + elseif ax == 4 then x = x + width/2 + end + if ot == 2 then + doffset, hoffset = hoffset, doffset + end + if ay == 1 then y = y - doffset + elseif ay == 2 then y = y + hoffset + elseif ay == 3 then y = y + (doffset + hoffset)/2 - doffset + end + elseif ot == 1 or ot == 3 then + if ay == 1 then y = y - height + elseif ay == 2 then y = y + height + elseif ay == 3 then y = y - height/2 + end + if ot == 1 then + doffset, hoffset = hoffset, doffset + end + if ax == 1 then x = x - width + elseif ax == 2 then x = x + width + elseif ax == 3 then x = x - width/2 + elseif ax == 4 then x = x + width/2 + elseif ax == 5 then x = x - hoffset + elseif ax == 6 then x = x + doffset + end + end + return ot, x + xoffset, y - yoffset + end + + -- to be checked: begin- or enddir kan nil zijn, weird + + -- local function calculate_width_to_enddir(this_box,begindir) -- can be a helper + -- local dir_nest = 1 + -- local enddir = begindir + -- for current, subtype in nextdir, getnext(begindir) do + -- if subtype == normaldir_code then -- todo + -- dir_nest = dir_nest + 1 + -- else + -- dir_nest = dir_nest - 1 + -- end + -- if dir_nest == 0 then -- does the type matter + -- enddir = current + -- local width = rangedimensions(this_box,begindir,enddir) + -- return enddir, width + -- end + -- end + -- if enddir == begindir then + -- local width = rangedimensions(this_box,begindir) -- ,enddir) + -- return enddir, width + -- end + -- return enddir, 0 + -- end + + -- check frequencies of nodes + + hlist_out = function(this_box,current) + local ref_h = pos_h + local ref_v = pos_v + local ref_r = pos_r + pos_r = getdirection(this_box) + local boxwidth, + boxheight, + boxdepth = getwhd(this_box) + + local cur_h = 0 + local cur_v = 0 + + -- if not current then + -- current = getlist(this_box) + -- end + + -- we can encounter localpar, boundary and penalty nodes but a special + -- iterator over content nodes won't save much + + for current, id, subtype in nextnode, current do + if id == glyph_code then + local char, font = isglyph(current) + local x_offset, y_offset = getoffsets(current) + if x_offset ~= 0 or y_offset ~= 0 then + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + x_offset) + else + pos_h = ref_h + (cur_h + x_offset) + end + pos_v = ref_v - (cur_v - y_offset) + -- synced + end + local wd = flush_character(current,font,char,false,true,pos_h,pos_v,pos_r) + cur_h = cur_h + wd + elseif id == glue_code then + local gluewidth = effectiveglue(current,this_box) + if gluewidth ~= 0 then + if subtype >= leaders_code then + local leader = getleader(current) + if leader then + local width, height, depth = getwhd(leader) + if getid(leader) == rule_code then + if gluewidth > 0 then + if height == running then + height = boxheight + end + if depth == running then + depth = boxdepth + end + local total = height + depth + if total > 0 then + if pos_r == righttoleft_code then + pos_h = pos_h - gluewidth + end + pos_v = pos_v - depth + flushrule(leader,pos_h,pos_v,pos_r,gluewidth,total,getsubtype(leader)) + end + cur_h = cur_h + gluewidth + end + elseif width > 0 and gluewidth > 0 then + local boxdir = getdirection(leader) or lefttoright_code + gluewidth = gluewidth + 10 + local edge = cur_h + gluewidth + local lx = 0 + if subtype == gleaders_code then + local save_h = cur_h + if pos_r == righttoleft_code then + cur_h = ref_h - shipbox_h - cur_h + cur_h = width * (cur_h / width) + cur_h = ref_h - shipbox_h - cur_h + else + cur_h = cur_h + ref_h - shipbox_h + cur_h = width * (cur_h / width) + cur_h = cur_h - ref_h - shipbox_h + end + if cur_h < save_h then + cur_h = cur_h + width + end + elseif subtype == leaders_code then + local save_h = cur_h + cur_h = width * (cur_h / width) + if cur_h < save_h then + cur_h = cur_h + width + end + else + lq = gluewidth / width + lr = gluewidth % width + if subtype == cleaders_code then + cur_h = cur_h + lr / 2 + else + lx = lr / (lq + 1) + cur_h = cur_h + (lr - (lq - 1) * lx) / 2 + end + end + local shift = getshift(leader) + leaderlevel = leaderlevel + 1 + while cur_h + width <= edge do + local basepoint_h = 0 + -- local basepoint_v = shift + if boxdir ~= pos_r then + basepoint_h = boxwidth + end + -- synch_pos_with_cur(ref_h,ref_v,cur_h + basepoint_h,shift) + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + basepoint_h) + else + pos_h = ref_h + (cur_h + basepoint_h) + end + pos_v = ref_v - shift + -- synced + if getid(leader) == vlist_code then + vlist_out(leader,getlist(leader)) + else + hlist_out(leader,getlist(leader)) + end + cur_h = cur_h + width + lx + end + leaderlevel = leaderlevel - 1 + cur_h = edge - 10 + else + cur_h = cur_h + gluewidth + end + else + cur_h = cur_h + gluewidth + end + else + if tospace and subtype == spaceskip_code then + -- todo: flush_space + flush_character(false,getfont(current),32,false,true,pos_h,pos_v,pos_r) + end + cur_h = cur_h + gluewidth + end + end + elseif id == hlist_code or id == vlist_code then + local width, height, depth = getwhd(current) + local list = getlist(current) + if list then + local boxdir = getdirection(current) or lefttoright_code + local shift, orientation = getshift(current) + if not orientation then + local basepoint_h = boxdir ~= pos_r and width or 0 + -- local basepoint_v = shift + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + basepoint_h) + else + pos_h = ref_h + (cur_h + basepoint_h) + end + pos_v = ref_v - shift + -- synced + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + elseif orientation == 0x1000 then + local orientation, xoffset, yoffset = getorientation(current) + local basepoint_h = boxdir ~= pos_r and width or 0 + -- local basepoint_v = shift + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + basepoint_h + xoffset) + else + pos_h = ref_h + (cur_h + basepoint_h + xoffset) + end + pos_v = ref_v - (shift - yoffset) + -- synced + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + else + local orientation, xoffset, yoffset, woffset, hoffset, doffset = getorientation(current) + local orientation, basepoint_h, basepoint_v = applyanchor(orientation,0,shift,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) + if orientation == 1 then + basepoint_h = basepoint_h + doffset + if boxdir == pos_r then + basepoint_v = basepoint_v - height + end + elseif orientation == 2 then + if boxdir == pos_r then + basepoint_h = basepoint_h + width + end + elseif orientation == 3 then + basepoint_h = basepoint_h + hoffset + if boxdir ~= pos_r then + basepoint_v = basepoint_v - height + end + end + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + basepoint_h) + else + pos_h = ref_h + (cur_h + basepoint_h) + end + pos_v = ref_v - (cur_v + basepoint_v) + -- synced + pushorientation(orientation,pos_h,pos_v,pos_r) + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + poporientation(orientation,pos_h,pos_v,pos_r) + end + end + cur_h = cur_h + width + elseif id == kern_code then + local kern, factor = getkern(current,true) + if kern ~= 0 then + if factor ~= 0 then + cur_h = cur_h + (1.0 + factor/1000000.0) * kern + else + cur_h = cur_h + kern + end + end + elseif id == rule_code then + local width, height, depth = getwhd(current) + if width > 0 then + if height == running then + height = boxheight + end + if depth == running then + depth = boxdepth + end + local total = height + depth + if total > 0 then + local xoffset, yoffset, left, right = getoffsets(current) -- top bottom + if left ~= 0 then + pos_v = pos_v + left + total = total - left + end + if right ~= 0 then + depth = depth - right + total = total - right + end + if pos_r == righttoleft_code then + pos_h = pos_h - width + xoffset = - xoffset + end + pos_v = pos_v - depth + flushrule(current,pos_h + xoffset,pos_v + yoffset,pos_r,width,total,subtype) + end + end + cur_h = cur_h + width + elseif id == math_code then + -- local kern = getkern(current) + -- if kern ~= 0 then + -- cur_h = cur_h + kern + -- else + cur_h = cur_h + effectiveglue(current,this_box) + -- end + elseif id == dir_code then + -- We normally have proper begin-end pairs. A begin without end is (silently) handled + -- and an end without a begin will be (silently) skipped we only need to move forward + -- so we then have a faster calculation. + local dir, cancel = getdirection(current) + if cancel then + local ds = dirstack[current] + if ds then + ref_h = ds.ref_h + ref_v = ds.ref_v + cur_h = ds.cur_h + cur_v = ds.cur_v + else + -- pardir + end + pos_r = dir + else + local width, enddir = dirdimensions(this_box,current) + local new_h = cur_h + width + if dir ~= pos_r then + cur_h = new_h + end + if enddir ~= current then + dirstack[enddir] = { + cur_h = new_h, + cur_v = cur_v, + ref_h = ref_h, + ref_v = ref_v, + } + setdirection(enddir,pos_r) + end + if pos_r == righttoleft_code then + pos_h = ref_h - cur_h + else + pos_h = ref_h + cur_h + end + pos_v = ref_v - cur_v + -- synced + ref_h = pos_h + ref_v = pos_v + cur_h = 0 + cur_v = 0 + pos_r = dir + goto synced + end + elseif id == whatsit_code then + if subtype == literalwhatsit_code then + flushliteral(current,pos_h,pos_v) + elseif subtype == lateluawhatsit_code then + flushlatelua(current,pos_h,pos_v) + elseif subtype == setmatrixwhatsit_code then + flushsetmatrix(current,pos_h,pos_v) + elseif subtype == savewhatsit_code then + flushsave(current,pos_h,pos_v) + elseif subtype == restorewhatsit_code then + flushrestore(current,pos_h,pos_v) + elseif subtype == saveposwhatsit_code then + last_position_x = pos_h + last_position_y = pos_v + elseif subtype == writewhatsit_code then + flushwriteout(current) + elseif subtype == closewhatsit_code then + flushcloseout(current) + elseif subtype == openwhatsit_code then + flushopenout(current) + end + elseif id == disc_code then + local replace, tail = getreplace(current) + if replace and subtype ~= select_disc then + -- we could flatten .. no gain + setlink(tail,getnext(current)) + setlink(current,replace) + setreplace(current) + end + -- elseif id == localpar_code and start_of_par(current) then + -- local pardir = getdirection(current) or lefttoright_code + -- if pardir == righttoleft_code then + -- end + -- end + else + -- penalty, boundary ... no dimensions + goto synced + end + -- There is no gain in skipping over this when we have zero progression + -- and such. + if pos_r == righttoleft_code then + pos_h = ref_h - cur_h + else + pos_h = ref_h + cur_h + end + pos_v = ref_v - cur_v + ::synced:: + end + pos_h = ref_h + pos_v = ref_v + pos_r = ref_r + end + + vlist_out = function(this_box,current) + local ref_h = pos_h + local ref_v = pos_v + local ref_r = pos_r + pos_r = getdirection(this_box) + + local boxwidth, + boxheight, + boxdepth = getwhd(this_box) + + local cur_h = 0 + local cur_v = - boxheight + local top_edge = cur_v + + if pos_r == righttoleft_code then + pos_h = ref_h - cur_h + else + pos_h = ref_h + cur_h + end + pos_v = ref_v - cur_v + -- synced + + -- if not current then + -- current = getlist(this_box) + -- end + + -- while current do + -- local id = getid(current) + for current, id, subtype in nextnode, current do + if id == glue_code then + local glueheight = effectiveglue(current,this_box) + if glueheight ~= 0 then + if subtype >= leaders_code then + local leader = getleader(current) + if leader then + local width, height, depth = getwhd(leader) + local total = height + depth + if getid(leader) == rule_code then + depth = 0 -- hm + if total > 0 then + if width == running then + width = boxwidth + end + if width > 0 then + if pos_r == righttoleft_code then + cur_h = cur_h - width + end + flushrule(leader,pos_h,pos_v - total,pos_r,width,total,getsubtype(leader)) + end + cur_v = cur_v + total + end + elseif total > 0 and glueheight > 0 then + glueheight = glueheight + 10 + local edge = cur_v + glueheight + local ly = 0 + if subtype == gleaders_code then + save_v = cur_v + cur_v = ref_v - shipbox_v - cur_v + cur_v = total * (cur_v / total) + cur_v = ref_v - shipbox_v - cur_v + if cur_v < save_v then + cur_v = cur_v + total + end + elseif subtype == leaders_code then -- aleader + save_v = cur_v + cur_v = top_edge + total * ((cur_v - top_edge) / total) + if cur_v < save_v then + cur_v = cur_v + total + end + else + lq = glueheight / total + lr = glueheight % total + if subtype == cleaders_code then + cur_v = cur_v + lr / 2 + else + ly = lr / (lq + 1) + cur_v = cur_v + (lr - (lq - 1) * ly) / 2 + end + end + local shift = getshift(leader) + leaderlevel = leaderlevel + 1 + while cur_v + total <= edge do -- todo: <= edge - total + -- synch_pos_with_cur(ref_h, ref_v, getshift(leader), cur_v + height) + if pos_r == righttoleft_code then + pos_h = ref_h - shift + else + pos_h = ref_h + shift + end + pos_v = ref_v - (cur_v + height) + -- synced + if getid(leader) == vlist_code then + vlist_out(leader,getlist(leader)) + else + hlist_out(leader,getlist(leader)) + end + cur_v = cur_v + total + ly + end + leaderlevel = leaderlevel - 1 + cur_v = edge - 10 + else + cur_v = cur_v + glueheight + end + end + else + cur_v = cur_v + glueheight + end + end + elseif id == hlist_code or id == vlist_code then + local width, height, depth = getwhd(current) + local list = getlist(current) + if list then + local boxdir = getdirection(current) or lefttoright_code + local shift, orientation = getshift(current) + if not orientation then + -- local basepoint_h = shift + -- local basepoint_v = height + if shift == 0 then + pos_h = ref_h + else + if boxdir ~= pos_r then + shift = shift + width + end + if pos_r == righttoleft_code then + pos_h = ref_h - shift + else + pos_h = ref_h + shift + end + end + pos_v = ref_v - (cur_v + height) + -- synced + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + elseif orientation == 0x1000 then + local orientation, xoffset, yoffset = getorientation(current) + -- local basepoint_h = shift + -- local basepoint_v = height + if boxdir ~= pos_r then + shift = shift + width + end + if pos_r == righttoleft_code then + pos_h = ref_h - (shift + xoffset) + else + pos_h = ref_h + (shift + xoffset) + end + pos_v = ref_v - (cur_v + height - yoffset) + -- synced + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + else + local orientation, xoffset, yoffset, woffset, hoffset, doffset = getorientation(current) + local orientation, basepoint_h, basepoint_v = applyanchor(orientation,shift,height,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) + if orientation == 1 then + basepoint_h = basepoint_h + width - height + basepoint_v = basepoint_v - height + elseif orientation == 2 then + basepoint_h = basepoint_h + width + basepoint_v = basepoint_v + depth - height + elseif orientation == 3 then -- weird + basepoint_h = basepoint_h + height + end + if pos_r == righttoleft_code then + pos_h = ref_h - basepoint_h + else + pos_h = ref_h + basepoint_h + end + pos_v = ref_v - (cur_v + basepoint_v) + -- synced + pushorientation(orientation,pos_h,pos_v,pos_r) + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + poporientation(orientation,pos_h,pos_v,pos_r) + end + end + cur_v = cur_v + height + depth + elseif id == kern_code then + cur_v = cur_v + getkern(current) + elseif id == rule_code then + local width, height, depth = getwhd(current) + local total = height + depth + if total > 0 then + if width == running then + width = boxwidth + end + if width > 0 then + local xoffset, yoffset, left, right = getoffsets(current) + if left ~= 0 then + width = width - left + xoffset = left + end + if right ~= 0 then + width = width - right + end + if pos_r == righttoleft_code then + xoffset = - xoffset - width + end + flushrule(current,pos_h + xoffset,pos_v - total - yoffset,pos_r,width,total,subtype) + end + end + cur_v = cur_v + total + elseif id == whatsit_code then + if subtype == literalwhatsit_code then + flushliteral(current,pos_h,pos_v) + elseif subtype == lateluawhatsit_code then + flushlatelua(current,pos_h,pos_v) + elseif subtype == setmatrixwhatsit_code then + flushsetmatrix(current,pos_h,pos_v) + elseif subtype == savewhatsit_code then + flushsave(current,pos_h,pos_v) + elseif subtype == restorewhatsit_code then + flushrestore(current,pos_h,pos_v) + elseif subtype == saveposwhatsit_code then + last_position_x = pos_h + last_position_y = pos_v + elseif subtype == writewhatsit_code then + flushwriteout(current) + elseif subtype == closewhatsit_code then + flushcloseout(current) + elseif subtype == openwhatsit_code then + flushopenout(current) + end + else + -- penalty + goto synced + end + if pos_r == righttoleft_code then + pos_h = ref_h - cur_h + else + pos_h = ref_h + cur_h + end + pos_v = ref_v - cur_v + ::synced:: + end + pos_h = ref_h + pos_v = ref_v + pos_r = ref_r + end + +end + +function drivers.converters.lmtx(driver,box,smode,objnum,specification) + + if not driver then + report("error in converter, no driver") + return + end + + if box then + box = tonut(box) + else + report("error in converter, no box") + return + end + + local actions = driver.actions + local flushers = driver.flushers + + initialize = actions.initialize + finalize = actions.finalize + + updatefontstate = flushers.updatefontstate + + pushorientation = flushers.pushorientation + poporientation = flushers.poporientation + + flushcharacter = flushers.character + flushfontchar = flushers.fontchar + flushrule = flushers.rule + flushsimplerule = flushers.simplerule + flushspecialrule = flushers.specialrule + flushspecial = flushers.special + flushliteral = flushers.literal + flushsetmatrix = flushers.setmatrix + flushsave = flushers.save + flushrestore = flushers.restore + -- flushimage = flushers.image + + reset_dir_stack() + reset_state() + + shippingmode = smode + + local details = nil -- must be outside labels + + local width, height, depth = getwhd(box) + + local total = height + depth + + ----- v_offset_par = 0 + ----- h_offset_par = 0 + + local max_v = total -- + v_offset_par + local max_h = width -- + h_offset_par + + if height > maxdimen or depth > maxdimen or width > maxdimen then + goto DONE + end + + if max_v > maxdimen then + goto DONE + elseif max_v > abs_max_v then + abs_max_v = max_v + end + + if max_h > maxdimen then + goto DONE + elseif max_h > abs_max_h then + abs_max_h = max_h + end + + if shippingmode == "page" then + + -- We have zero offsets in ConTeXt. + + local pagewidth, pageheight = getpagedimensions() + + -- local h_offset_par = texget("hoffset") + -- local v_offset_par = texget("voffset") + + -- page_h_origin = trueinch + -- page_v_origin = trueinch + + pos_r = lefttoright_code + + if pagewidth > 0 then + page_size_h = pagewidth + else + page_size_h = width + end + + if page_size_h == 0 then + page_size_h = width + end + + if pageheight > 0 then + page_size_v = pageheight + else + page_size_v = total + end + + if page_size_v == 0 then + page_size_v = total + end + + local refpoint_h = 0 -- + page_h_origin + h_offset_par + local refpoint_v = page_size_v -- - page_v_origin - v_offset_par + + pos_h = refpoint_h + pos_v = refpoint_v - height + -- synced + + else + + -- page_h_origin = 0 + -- page_v_origin = 0 + page_size_h = width + page_size_v = total + pos_r = getdirection(box) + pos_v = depth + pos_h = pos_r == righttoleft_code and width or 0 + + end + + shipbox_ref_h = pos_h + shipbox_ref_v = pos_v + + details = { + shippingmode = smode, -- target + boundingbox = { 0, 0, page_size_h, page_size_v }, + objectnumber = smode ~= "page" and objnum or nil, + pagenumber = smode == "page" and objnum or nil, + specification = specification, + } + + initialize(driver,details) + + lastfont = nil -- this forces a sync each page / object + + if getid(box) == vlist_code then + vlist_out(box,getlist(box)) + else + hlist_out(box,getlist(box)) + end + + ::DONE:: + + finalize(driver,details) + + shippingmode = "none" +end + +-- This will move to back-out.lua eventually. + +do + + ----- sortedhash = table.sortedhash + + ----- tonut = nodes.tonut + local properties = nodes.properties.data + local flush = texio.write_nl + + local periods = utilities.strings.newrepeater(".") + + local function showdetails(n,l) + local p = properties[tonut(n)] + if p then + local done = false + for k, v in sortedhash(p) do + if done then + flush("\n") + else + done = true + end + flush(periods[l+1] .. " " .. k .. " = " .. tostring(v)) + end + end + end + + local whatsittracers = { + latelua = showdetails, + literal = showdetails, + } + + callback.register("show_whatsit",function(n,l) + local s = nodes.whatsitcodes[n.subtype] + texio.write(" [" .. s .. "]") + local w = whatsittracers[s] + if w then + w(n,l) + end + end) + +end diff --git a/tex/context/base/mkiv/driv-shp.lua b/tex/context/base/mkiv/driv-shp.lua deleted file mode 100644 index a23cca3a8..000000000 --- a/tex/context/base/mkiv/driv-shp.lua +++ /dev/null @@ -1,1337 +0,0 @@ -if not modules then modules = { } end modules ['driv-shp'] = { - version = 1.001, - optimize = true, - comment = "companion to driv-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local type, next = type, next -local round = math.round - -local setmetatableindex = table.setmetatableindex -local formatters = string.formatters -local concat = table.concat -local keys = table.keys -local sortedhash = table.sortedhash -local splitstring = string.split -local idiv = number.idiv -local extract = bit32.extract -local nuts = nodes.nuts - -local tonut = nodes.tonut -local tonode = nodes.tonode - -local getdirection = nuts.getdirection -local getlist = nuts.getlist -local getoffsets = nuts.getoffsets -local getorientation = nuts.getorientation -local getfield = nuts.getfield -local getwhd = nuts.getwhd -local getkern = nuts.getkern -local getheight = nuts.getheight -local getdepth = nuts.getdepth ------ getwidth = nuts.getwidth -local getnext = nuts.getnext -local getsubtype = nuts.getsubtype -local getid = nuts.getid -local getleader = nuts.getleader ------ getglue = nuts.getglue -local getshift = nuts.getshift -local getdata = nuts.getdata ------ getexpansion = nuts.getexpansion -local getreplace = nuts.getreplace -local setreplace = nuts.setreplace -local getfont = nuts.getfont - -local setdirection = nuts.setdirection -local setfield = nuts.setfield -local setlink = nuts.setlink - -local isglyph = nuts.isglyph -local findtail = nuts.tail -local nextdir = nuts.traversers.dir -local nextnode = nuts.traversers.node - -local rangedimensions = node.direct.rangedimensions -- nuts ? -local effectiveglue = nuts.effective_glue -local start_of_par = nuts.start_of_par -local dirdimensions = nuts.dirdimensions - -local texget = tex.get - -local fonthashes = fonts.hashes -local fontdata = fonthashes.identifiers -local characters = fonthashes.characters -local parameters = fonthashes.parameters - -local nodecodes = nodes.nodecodes -local whatsitcodes = nodes.whatsitcodes -local leadercodes = nodes.leadercodes -local gluecodes = nodes.gluecodes -local dircodes = nodes.dircodes -local dirvalues = nodes.dirvalues -local subtypes = nodes.subtypes - -local normaldir_code = dircodes.normal - -local lefttoright_code = dirvalues.lefttoright -local righttoleft_code = dirvalues.righttoleft - -local glyph_code = nodecodes.glyph -local kern_code = nodecodes.kern -local glue_code = nodecodes.glue -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local dir_code = nodecodes.dir -local disc_code = nodecodes.disc -local math_code = nodecodes.math -local rule_code = nodecodes.rule -local whatsit_code = nodecodes.whatsit ------ penalty_code = nodecodes.penalty ------ boundary_code = nodecodes.boundary - -local leaders_code = leadercodes.leaders -local cleaders_code = leadercodes.cleaders -local xleaders_code = leadercodes.xleaders -local gleaders_code = leadercodes.gleaders - -local spaceskip_code = gluecodes.spaceskip - -local saveposwhatsit_code = whatsitcodes.savepos -local userdefinedwhatsit_code = whatsitcodes.userdefined -local openwhatsit_code = whatsitcodes.open -local writewhatsit_code = whatsitcodes.write -local closewhatsit_code = whatsitcodes.close -local lateluawhatsit_code = whatsitcodes.latelua -local literalwhatsit_code = whatsitcodes.literal -local setmatrixwhatsit_code = whatsitcodes.setmatrix -local savewhatsit_code = whatsitcodes.save -local restorewhatsit_code = whatsitcodes.restore - -local getpagedimensions getpagedimensions = function() - getpagedimensions = backends.codeinjections.getpagedimensions - return getpagedimensions() -end - -local drivers = drivers -local instances = drivers.instances - -local report = logs.reporter("drivers") - ---------------------------------------------------------------------------------------- - -local lastfont = nil -local fontcharacters = nil - -local magicconstants = tex.magicconstants -local trueinch = magicconstants.trueinch -local maxdimen = magicconstants.maxdimen -local running = magicconstants.running - -local pos_h = 0 -local pos_v = 0 -local pos_r = lefttoright_code -local shippingmode = "none" - -local abs_max_v = 0 -local abs_max_h = 0 - -local shipbox_h = 0 -local shipbox_v = 0 -local page_size_h = 0 -local page_size_v = 0 ------ page_h_origin = 0 -- trueinch ------ page_v_origin = 0 -- trueinch - -local initialize -local finalize -local updatefontstate -local pushorientation -local poporientation -local flushcharacter -local flushfontchar -local flushrule -local flushliteral -local flushsetmatrix -local flushsave -local flushrestore -local flushspecial ------ flushimage - --- make local - -function drivers.getpos () return round(pos_h), round(pos_v) end -function drivers.getrpos() return round(pos_h), round(pos_v), pos_r end -function drivers.gethpos() return round(pos_h) end -function drivers.getvpos() return round(pos_v) end - --- characters - -local flush_character - -local stack = setmetatableindex("table") -local level = 0 -local nesting = 0 -local main = 0 - --- experiment (smaller page stream but might be fragile) - -local tospace = false directives.register("backends.spaces", function(v) tospace = v end) - --- todo: cache streams - -local function flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommands) - - if nesting > 100 then - return - elseif nesting == 0 then - main = font - end - - nesting = nesting + 1 - - local saved_h = pos_h - local saved_v = pos_v - local saved_r = pos_r - pos_r = lefttoright_code - - local data = fontdata[font] - local fnt = font - local fonts = data.fonts - local siz = (data.parameters.factor or 1)/65536 - - local function flushchar(font,char,fnt,chr,f,e) - if fnt then - local nest = char ~= chr or font ~= fnt - if fnt == 0 then - fnt = main - end - return flush_character(false,fnt,chr,factor,nest,pos_h,pos_v,pos_r,f,e) - else - return 0 - end - end - - -- we assume resolved fonts: id mandate but maybe also size - - for i=1,#vfcommands do - local packet = vfcommands[i] - local command = packet[1] - if command == "char" then - local chr = packet[2] - local f = packet[3] - local e = packet[4] - pos_h = pos_h + flushchar(font,char,fnt,chr,f,e) - elseif command == "slot" then - local index = packet[2] - local chr = packet[3] - local f = packet[4] - local e = packet[5] - if index == 0 then - pos_h = pos_h + flushchar(font,char,font,chr,f,e) - else - local okay = fonts and fonts[index] - if okay then - local fnt = okay.id - if fnt then - pos_h = pos_h + flushchar(font,char,fnt,chr,f,e) - end - else - -- safeguard, we assume the font itself (often index 1) - pos_h = pos_h + flushchar(font,char,font,chr,f,e) - end - end - elseif command == "use" then - local index = packet[2] - if index then - local fnt - if index == 0 then - fnt = font - else - local okay = fonts and fonts[index] - if okay then - fnt = okay.id - end - end - if fnt then - -- not efficient but ok for now as experiment - local d = characters[fnt] - if d then - for i=3,#packet do - local chr = packet[i] - local dat = d[chr] - if dat then - flushfontchar(fnt,chr,dat) - end - end - end - end - end - elseif command == "right" then - local h = packet[2] -- * siz - if factor ~= 0 and h ~= 0 then - h = h + h * factor / 1000 -- expansion - end - pos_h = pos_h + h - elseif command == "down" then - local v = packet[2] -- * siz - pos_v = pos_v - v - elseif command == "push" then - level = level + 1 - local s = stack[level] - s[1] = pos_h - s[2] = pos_v - elseif command == "pop" then - if level > 0 then - local s = stack[level] - pos_h = s[1] - pos_v = s[2] - level = level - 1 - end - elseif command == "pdf" then - flushliteral(false,pos_h,pos_v,packet[2],packet[3]) - elseif command == "rule" then - local size_v = packet[2] - local size_h = packet[3] - if factor ~= 0 and size_h > 0 then - size_h = size_h + size_h * factor / 1000 - end - if size_h > 0 and size_v > 0 then - flushsimplerule(pos_h,pos_v,pos_r,size_h,size_v) - pos_h = pos_h + size_h - end - elseif command == "font" then - local index = packet[2] - local okay = fonts and fonts[index] - if okay then - fnt = okay.id or fnt -- or maybe just return - end - elseif command == "lua" then - local code = packet[2] - if type(code) ~= "function" then - code = loadstring(code) - end - if type(code) == "function" then - code(font,char,pos_h,pos_v) - end - elseif command == "node" then - local h = packet[2] - hlist_out(h,getlist(h)) - elseif command == "image" then - -- doesn't work because intercepted by engine so we use a different - -- mechanism (for now) - local image = packet[2] - -- to do - elseif command == "pdfmode" then - -- doesn't happen - -- elseif command == "special" then - -- -- not supported - -- elseif command == "nop" then - -- -- nothing to do| - -- elseif command == "scale" then - -- -- not supported - end - end - - pos_h = saved_h - pos_v = saved_v - pos_r = saved_r - - nesting = nesting - 1 -end - -local onetimemessage -- could be defined later (todo: make plug for this) - -flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r,f,e) - - if font ~= lastfont then - lastfont = font - fontcharacters = characters[font] - updatefontstate(font) - end - - local data = fontcharacters[char] - if not data then - if char > 0 then - if not onetimemessage then - onetimemessage = fonts.loggers.onetimemessage - end - onetimemessage(font,char,"missing") - end - return 0, 0, 0 - end - - local width, height, depth, naturalwidth - if current then - naturalwidth, height, depth, factor = getwhd(current,true) -- also get corrected width - if factor == 0 then - width = naturalwidth - else - -- width = (1.0 + factor/1000000.0) * naturalwidth - width = naturalwidth + naturalwidth * factor/1000000.0 - -- width = naturalwidth + naturalwidth * 0.000001 * factor - end - else - width = data.width or 0 - height = data.height or 0 - depth = data.depth or 0 - naturalwidth = width - if not factor then - factor = 0 - end - end - - if pos_r == righttoleft_code then - pos_h = pos_h - width - end - if vfcommands then - vfcommands = data.commands - end - if vfcommands then - flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommands) -- also f ? - else - -- kind of messy that we do orientation here and offsets elsewhere - local orientation = data.orientation - if orientation and (orientation == 1 or orientation == 3) then - local x = data.xoffset - local y = data.yoffset - if x then - pos_h = pos_h + x - end - if y then - pos_v = pos_v + y - end - pushorientation(orientation,pos_h,pos_v) - flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) - poporientation(orientation,pos_h,pos_v) - else - flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) - end - end - return width, height, depth -end - --- end of characters - -local function reset_state() - pos_h = 0 - pos_v = 0 - pos_r = lefttoright_code - shipbox_h = 0 - shipbox_v = 0 - shippingmode = "none" - page_size_h = 0 - page_size_v = 0 - -- page_h_origin = 0 -- trueinch - -- page_v_origin = 0 -- trueinch -end - --- local function dirstackentry(t,k) --- local v = { --- cur_h = 0, --- cur_v = 0, --- ref_h = 0, --- ref_v = 0, --- } --- t[k] = v --- return v --- end --- --- local dirstack = setmetatableindex(dirstackentry) --- --- local function reset_dir_stack() --- dirstack = setmetatableindex(dirstackentry) --- end - -local dirstack = { } - -local function reset_dir_stack() - dirstack = { } -end - -local leaderlevel = 0 - -local function flushlatelua(current,h,v) - -- Here we assume maganement by the lua function so currently we don't - -- check for leaderlevel. - return backends.latelua(current,h,v) -end - -local function flushwriteout(current) - if leaderlevel == 0 then - backends.writeout(current) - end -end - -local function flushopenout(current) - if leaderlevel == 0 then - backends.openout(current) - end -end - -local function flushcloseout(current) - if leaderlevel == 0 then - backends.closeout(current) - end -end - -local hlist_out, vlist_out do - - local function applyanchor(orientation,x,y,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) - local ot = extract(orientation, 0,4) - local ay = extract(orientation, 4,4) - local ax = extract(orientation, 8,4) - local of = extract(orientation,12,4) - if ot == 4 then - ot, ay = 0, 1 - elseif ot == 5 then - ot, ay = 0, 2 - end - if ot == 0 or ot == 2 then - if ax == 1 then x = x - width - elseif ax == 2 then x = x + width - elseif ax == 3 then x = x - width/2 - elseif ax == 4 then x = x + width/2 - end - if ot == 2 then - doffset, hoffset = hoffset, doffset - end - if ay == 1 then y = y - doffset - elseif ay == 2 then y = y + hoffset - elseif ay == 3 then y = y + (doffset + hoffset)/2 - doffset - end - elseif ot == 1 or ot == 3 then - if ay == 1 then y = y - height - elseif ay == 2 then y = y + height - elseif ay == 3 then y = y - height/2 - end - if ot == 1 then - doffset, hoffset = hoffset, doffset - end - if ax == 1 then x = x - width - elseif ax == 2 then x = x + width - elseif ax == 3 then x = x - width/2 - elseif ax == 4 then x = x + width/2 - elseif ax == 5 then x = x - hoffset - elseif ax == 6 then x = x + doffset - end - end - return ot, x + xoffset, y - yoffset - end - - -- to be checked: begin- or enddir kan nil zijn, weird - - -- local function calculate_width_to_enddir(this_box,begindir) -- can be a helper - -- local dir_nest = 1 - -- local enddir = begindir - -- for current, subtype in nextdir, getnext(begindir) do - -- if subtype == normaldir_code then -- todo - -- dir_nest = dir_nest + 1 - -- else - -- dir_nest = dir_nest - 1 - -- end - -- if dir_nest == 0 then -- does the type matter - -- enddir = current - -- local width = rangedimensions(this_box,begindir,enddir) - -- return enddir, width - -- end - -- end - -- if enddir == begindir then - -- local width = rangedimensions(this_box,begindir) -- ,enddir) - -- return enddir, width - -- end - -- return enddir, 0 - -- end - - -- check frequencies of nodes - - hlist_out = function(this_box,current) - local ref_h = pos_h - local ref_v = pos_v - local ref_r = pos_r - pos_r = getdirection(this_box) - local boxwidth, - boxheight, - boxdepth = getwhd(this_box) - - local cur_h = 0 - local cur_v = 0 - - -- if not current then - -- current = getlist(this_box) - -- end - - -- we can encounter localpar, boundary and penalty nodes but a special - -- iterator over content nodes won't save much - - for current, id, subtype in nextnode, current do - if id == glyph_code then - local char, font = isglyph(current) - local x_offset, y_offset = getoffsets(current) - if x_offset ~= 0 or y_offset ~= 0 then - if pos_r == righttoleft_code then - pos_h = ref_h - (cur_h + x_offset) - else - pos_h = ref_h + (cur_h + x_offset) - end - pos_v = ref_v - (cur_v - y_offset) - -- synced - end - local wd = flush_character(current,font,char,false,true,pos_h,pos_v,pos_r) - cur_h = cur_h + wd - elseif id == glue_code then - local gluewidth = effectiveglue(current,this_box) - if gluewidth ~= 0 then - if subtype >= leaders_code then - local leader = getleader(current) - if leader then - local width, height, depth = getwhd(leader) - if getid(leader) == rule_code then - if gluewidth > 0 then - if height == running then - height = boxheight - end - if depth == running then - depth = boxdepth - end - local total = height + depth - if total > 0 then - if pos_r == righttoleft_code then - pos_h = pos_h - gluewidth - end - pos_v = pos_v - depth - flushrule(leader,pos_h,pos_v,pos_r,gluewidth,total,getsubtype(leader)) - end - cur_h = cur_h + gluewidth - end - elseif width > 0 and gluewidth > 0 then - local boxdir = getdirection(leader) or lefttoright_code - gluewidth = gluewidth + 10 - local edge = cur_h + gluewidth - local lx = 0 - if subtype == gleaders_code then - local save_h = cur_h - if pos_r == righttoleft_code then - cur_h = ref_h - shipbox_h - cur_h - cur_h = width * (cur_h / width) - cur_h = ref_h - shipbox_h - cur_h - else - cur_h = cur_h + ref_h - shipbox_h - cur_h = width * (cur_h / width) - cur_h = cur_h - ref_h - shipbox_h - end - if cur_h < save_h then - cur_h = cur_h + width - end - elseif subtype == leaders_code then - local save_h = cur_h - cur_h = width * (cur_h / width) - if cur_h < save_h then - cur_h = cur_h + width - end - else - lq = gluewidth / width - lr = gluewidth % width - if subtype == cleaders_code then - cur_h = cur_h + lr / 2 - else - lx = lr / (lq + 1) - cur_h = cur_h + (lr - (lq - 1) * lx) / 2 - end - end - local shift = getshift(leader) - leaderlevel = leaderlevel + 1 - while cur_h + width <= edge do - local basepoint_h = 0 - -- local basepoint_v = shift - if boxdir ~= pos_r then - basepoint_h = boxwidth - end - -- synch_pos_with_cur(ref_h,ref_v,cur_h + basepoint_h,shift) - if pos_r == righttoleft_code then - pos_h = ref_h - (cur_h + basepoint_h) - else - pos_h = ref_h + (cur_h + basepoint_h) - end - pos_v = ref_v - shift - -- synced - if getid(leader) == vlist_code then - vlist_out(leader,getlist(leader)) - else - hlist_out(leader,getlist(leader)) - end - cur_h = cur_h + width + lx - end - leaderlevel = leaderlevel - 1 - cur_h = edge - 10 - else - cur_h = cur_h + gluewidth - end - else - cur_h = cur_h + gluewidth - end - else - if tospace and subtype == spaceskip_code then - -- todo: flush_space - flush_character(false,getfont(current),32,false,true,pos_h,pos_v,pos_r) - end - cur_h = cur_h + gluewidth - end - end - elseif id == hlist_code or id == vlist_code then - local width, height, depth = getwhd(current) - local list = getlist(current) - if list then - local boxdir = getdirection(current) or lefttoright_code - local shift, orientation = getshift(current) - if not orientation then - local basepoint_h = boxdir ~= pos_r and width or 0 - -- local basepoint_v = shift - if pos_r == righttoleft_code then - pos_h = ref_h - (cur_h + basepoint_h) - else - pos_h = ref_h + (cur_h + basepoint_h) - end - pos_v = ref_v - shift - -- synced - if id == vlist_code then - vlist_out(current,list) - else - hlist_out(current,list) - end - elseif orientation == 0x1000 then - local orientation, xoffset, yoffset = getorientation(current) - local basepoint_h = boxdir ~= pos_r and width or 0 - -- local basepoint_v = shift - if pos_r == righttoleft_code then - pos_h = ref_h - (cur_h + basepoint_h + xoffset) - else - pos_h = ref_h + (cur_h + basepoint_h + xoffset) - end - pos_v = ref_v - (shift - yoffset) - -- synced - if id == vlist_code then - vlist_out(current,list) - else - hlist_out(current,list) - end - else - local orientation, xoffset, yoffset, woffset, hoffset, doffset = getorientation(current) - local orientation, basepoint_h, basepoint_v = applyanchor(orientation,0,shift,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) - if orientation == 1 then - basepoint_h = basepoint_h + doffset - if boxdir == pos_r then - basepoint_v = basepoint_v - height - end - elseif orientation == 2 then - if boxdir == pos_r then - basepoint_h = basepoint_h + width - end - elseif orientation == 3 then - basepoint_h = basepoint_h + hoffset - if boxdir ~= pos_r then - basepoint_v = basepoint_v - height - end - end - if pos_r == righttoleft_code then - pos_h = ref_h - (cur_h + basepoint_h) - else - pos_h = ref_h + (cur_h + basepoint_h) - end - pos_v = ref_v - (cur_v + basepoint_v) - -- synced - pushorientation(orientation,pos_h,pos_v,pos_r) - if id == vlist_code then - vlist_out(current,list) - else - hlist_out(current,list) - end - poporientation(orientation,pos_h,pos_v,pos_r) - end - end - cur_h = cur_h + width - elseif id == kern_code then - local kern, factor = getkern(current,true) - if kern ~= 0 then - if factor ~= 0 then - cur_h = cur_h + (1.0 + factor/1000000.0) * kern - else - cur_h = cur_h + kern - end - end - elseif id == rule_code then - local width, height, depth = getwhd(current) - if width > 0 then - if height == running then - height = boxheight - end - if depth == running then - depth = boxdepth - end - local total = height + depth - if total > 0 then - local xoffset, yoffset, left, right = getoffsets(current) -- top bottom - if left ~= 0 then - pos_v = pos_v + left - total = total - left - end - if right ~= 0 then - depth = depth - right - total = total - right - end - if pos_r == righttoleft_code then - pos_h = pos_h - width - xoffset = - xoffset - end - pos_v = pos_v - depth - flushrule(current,pos_h + xoffset,pos_v + yoffset,pos_r,width,total,subtype) - end - end - cur_h = cur_h + width - elseif id == math_code then - -- local kern = getkern(current) - -- if kern ~= 0 then - -- cur_h = cur_h + kern - -- else - cur_h = cur_h + effectiveglue(current,this_box) - -- end - elseif id == dir_code then - -- We normally have proper begin-end pairs. A begin without end is (silently) handled - -- and an end without a begin will be (silently) skipped we only need to move forward - -- so we then have a faster calculation. - local dir, cancel = getdirection(current) - if cancel then - local ds = dirstack[current] - if ds then - ref_h = ds.ref_h - ref_v = ds.ref_v - cur_h = ds.cur_h - cur_v = ds.cur_v - else - -- pardir - end - pos_r = dir - else - local width, enddir = dirdimensions(this_box,current) - local new_h = cur_h + width - if dir ~= pos_r then - cur_h = new_h - end - if enddir ~= current then - dirstack[enddir] = { - cur_h = new_h, - cur_v = cur_v, - ref_h = ref_h, - ref_v = ref_v, - } - setdirection(enddir,pos_r) - end - if pos_r == righttoleft_code then - pos_h = ref_h - cur_h - else - pos_h = ref_h + cur_h - end - pos_v = ref_v - cur_v - -- synced - ref_h = pos_h - ref_v = pos_v - cur_h = 0 - cur_v = 0 - pos_r = dir - goto synced - end - elseif id == whatsit_code then - if subtype == literalwhatsit_code then - flushliteral(current,pos_h,pos_v) - elseif subtype == lateluawhatsit_code then - flushlatelua(current,pos_h,pos_v) - elseif subtype == setmatrixwhatsit_code then - flushsetmatrix(current,pos_h,pos_v) - elseif subtype == savewhatsit_code then - flushsave(current,pos_h,pos_v) - elseif subtype == restorewhatsit_code then - flushrestore(current,pos_h,pos_v) - elseif subtype == saveposwhatsit_code then - last_position_x = pos_h - last_position_y = pos_v - elseif subtype == writewhatsit_code then - flushwriteout(current) - elseif subtype == closewhatsit_code then - flushcloseout(current) - elseif subtype == openwhatsit_code then - flushopenout(current) - end - elseif id == disc_code then - local replace, tail = getreplace(current) - if replace and subtype ~= select_disc then - -- we could flatten .. no gain - setlink(tail,getnext(current)) - setlink(current,replace) - setreplace(current) - end - -- elseif id == localpar_code and start_of_par(current) then - -- local pardir = getdirection(current) or lefttoright_code - -- if pardir == righttoleft_code then - -- end - -- end - else - -- penalty, boundary ... no dimensions - goto synced - end - -- There is no gain in skipping over this when we have zero progression - -- and such. - if pos_r == righttoleft_code then - pos_h = ref_h - cur_h - else - pos_h = ref_h + cur_h - end - pos_v = ref_v - cur_v - ::synced:: - end - pos_h = ref_h - pos_v = ref_v - pos_r = ref_r - end - - vlist_out = function(this_box,current) - local ref_h = pos_h - local ref_v = pos_v - local ref_r = pos_r - pos_r = getdirection(this_box) - - local boxwidth, - boxheight, - boxdepth = getwhd(this_box) - - local cur_h = 0 - local cur_v = - boxheight - local top_edge = cur_v - - if pos_r == righttoleft_code then - pos_h = ref_h - cur_h - else - pos_h = ref_h + cur_h - end - pos_v = ref_v - cur_v - -- synced - - -- if not current then - -- current = getlist(this_box) - -- end - - -- while current do - -- local id = getid(current) - for current, id, subtype in nextnode, current do - if id == glue_code then - local glueheight = effectiveglue(current,this_box) - if glueheight ~= 0 then - if subtype >= leaders_code then - local leader = getleader(current) - if leader then - local width, height, depth = getwhd(leader) - local total = height + depth - if getid(leader) == rule_code then - depth = 0 -- hm - if total > 0 then - if width == running then - width = boxwidth - end - if width > 0 then - if pos_r == righttoleft_code then - cur_h = cur_h - width - end - flushrule(leader,pos_h,pos_v - total,pos_r,width,total,getsubtype(leader)) - end - cur_v = cur_v + total - end - elseif total > 0 and glueheight > 0 then - glueheight = glueheight + 10 - local edge = cur_v + glueheight - local ly = 0 - if subtype == gleaders_code then - save_v = cur_v - cur_v = ref_v - shipbox_v - cur_v - cur_v = total * (cur_v / total) - cur_v = ref_v - shipbox_v - cur_v - if cur_v < save_v then - cur_v = cur_v + total - end - elseif subtype == leaders_code then -- aleader - save_v = cur_v - cur_v = top_edge + total * ((cur_v - top_edge) / total) - if cur_v < save_v then - cur_v = cur_v + total - end - else - lq = glueheight / total - lr = glueheight % total - if subtype == cleaders_code then - cur_v = cur_v + lr / 2 - else - ly = lr / (lq + 1) - cur_v = cur_v + (lr - (lq - 1) * ly) / 2 - end - end - local shift = getshift(leader) - leaderlevel = leaderlevel + 1 - while cur_v + total <= edge do -- todo: <= edge - total - -- synch_pos_with_cur(ref_h, ref_v, getshift(leader), cur_v + height) - if pos_r == righttoleft_code then - pos_h = ref_h - shift - else - pos_h = ref_h + shift - end - pos_v = ref_v - (cur_v + height) - -- synced - if getid(leader) == vlist_code then - vlist_out(leader,getlist(leader)) - else - hlist_out(leader,getlist(leader)) - end - cur_v = cur_v + total + ly - end - leaderlevel = leaderlevel - 1 - cur_v = edge - 10 - else - cur_v = cur_v + glueheight - end - end - else - cur_v = cur_v + glueheight - end - end - elseif id == hlist_code or id == vlist_code then - local width, height, depth = getwhd(current) - local list = getlist(current) - if list then - local boxdir = getdirection(current) or lefttoright_code - local shift, orientation = getshift(current) - if not orientation then - -- local basepoint_h = shift - -- local basepoint_v = height - if shift == 0 then - pos_h = ref_h - else - if boxdir ~= pos_r then - shift = shift + width - end - if pos_r == righttoleft_code then - pos_h = ref_h - shift - else - pos_h = ref_h + shift - end - end - pos_v = ref_v - (cur_v + height) - -- synced - if id == vlist_code then - vlist_out(current,list) - else - hlist_out(current,list) - end - elseif orientation == 0x1000 then - local orientation, xoffset, yoffset = getorientation(current) - -- local basepoint_h = shift - -- local basepoint_v = height - if boxdir ~= pos_r then - shift = shift + width - end - if pos_r == righttoleft_code then - pos_h = ref_h - (shift + xoffset) - else - pos_h = ref_h + (shift + xoffset) - end - pos_v = ref_v - (cur_v + height - yoffset) - -- synced - if id == vlist_code then - vlist_out(current,list) - else - hlist_out(current,list) - end - else - local orientation, xoffset, yoffset, woffset, hoffset, doffset = getorientation(current) - local orientation, basepoint_h, basepoint_v = applyanchor(orientation,shift,height,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) - if orientation == 1 then - basepoint_h = basepoint_h + width - height - basepoint_v = basepoint_v - height - elseif orientation == 2 then - basepoint_h = basepoint_h + width - basepoint_v = basepoint_v + depth - height - elseif orientation == 3 then -- weird - basepoint_h = basepoint_h + height - end - if pos_r == righttoleft_code then - pos_h = ref_h - basepoint_h - else - pos_h = ref_h + basepoint_h - end - pos_v = ref_v - (cur_v + basepoint_v) - -- synced - pushorientation(orientation,pos_h,pos_v,pos_r) - if id == vlist_code then - vlist_out(current,list) - else - hlist_out(current,list) - end - poporientation(orientation,pos_h,pos_v,pos_r) - end - end - cur_v = cur_v + height + depth - elseif id == kern_code then - cur_v = cur_v + getkern(current) - elseif id == rule_code then - local width, height, depth = getwhd(current) - local total = height + depth - if total > 0 then - if width == running then - width = boxwidth - end - if width > 0 then - local xoffset, yoffset, left, right = getoffsets(current) - if left ~= 0 then - width = width - left - xoffset = left - end - if right ~= 0 then - width = width - right - end - if pos_r == righttoleft_code then - xoffset = - xoffset - width - end - flushrule(current,pos_h + xoffset,pos_v - total - yoffset,pos_r,width,total,subtype) - end - end - cur_v = cur_v + total - elseif id == whatsit_code then - if subtype == literalwhatsit_code then - flushliteral(current,pos_h,pos_v) - elseif subtype == lateluawhatsit_code then - flushlatelua(current,pos_h,pos_v) - elseif subtype == setmatrixwhatsit_code then - flushsetmatrix(current,pos_h,pos_v) - elseif subtype == savewhatsit_code then - flushsave(current,pos_h,pos_v) - elseif subtype == restorewhatsit_code then - flushrestore(current,pos_h,pos_v) - elseif subtype == saveposwhatsit_code then - last_position_x = pos_h - last_position_y = pos_v - elseif subtype == writewhatsit_code then - flushwriteout(current) - elseif subtype == closewhatsit_code then - flushcloseout(current) - elseif subtype == openwhatsit_code then - flushopenout(current) - end - else - -- penalty - goto synced - end - if pos_r == righttoleft_code then - pos_h = ref_h - cur_h - else - pos_h = ref_h + cur_h - end - pos_v = ref_v - cur_v - ::synced:: - end - pos_h = ref_h - pos_v = ref_v - pos_r = ref_r - end - -end - -function drivers.converters.lmtx(driver,box,smode,objnum,specification) - - if not driver then - report("error in converter, no driver") - return - end - - if box then - box = tonut(box) - else - report("error in converter, no box") - return - end - - local actions = driver.actions - local flushers = driver.flushers - - initialize = actions.initialize - finalize = actions.finalize - - updatefontstate = flushers.updatefontstate - - pushorientation = flushers.pushorientation - poporientation = flushers.poporientation - - flushcharacter = flushers.character - flushfontchar = flushers.fontchar - flushrule = flushers.rule - flushsimplerule = flushers.simplerule - flushspecial = flushers.special - flushliteral = flushers.literal - flushsetmatrix = flushers.setmatrix - flushsave = flushers.save - flushrestore = flushers.restore - -- flushimage = flushers.image - - reset_dir_stack() - reset_state() - - shippingmode = smode - - local details = nil -- must be outside labels - - local width, height, depth = getwhd(box) - - local total = height + depth - - ----- v_offset_par = 0 - ----- h_offset_par = 0 - - local max_v = total -- + v_offset_par - local max_h = width -- + h_offset_par - - if height > maxdimen or depth > maxdimen or width > maxdimen then - goto DONE - end - - if max_v > maxdimen then - goto DONE - elseif max_v > abs_max_v then - abs_max_v = max_v - end - - if max_h > maxdimen then - goto DONE - elseif max_h > abs_max_h then - abs_max_h = max_h - end - - if shippingmode == "page" then - - -- We have zero offsets in ConTeXt. - - local pagewidth, pageheight = getpagedimensions() - - -- local h_offset_par = texget("hoffset") - -- local v_offset_par = texget("voffset") - - -- page_h_origin = trueinch - -- page_v_origin = trueinch - - pos_r = lefttoright_code - - if pagewidth > 0 then - page_size_h = pagewidth - else - page_size_h = width - end - - if page_size_h == 0 then - page_size_h = width - end - - if pageheight > 0 then - page_size_v = pageheight - else - page_size_v = total - end - - if page_size_v == 0 then - page_size_v = total - end - - local refpoint_h = 0 -- + page_h_origin + h_offset_par - local refpoint_v = page_size_v -- - page_v_origin - v_offset_par - - pos_h = refpoint_h - pos_v = refpoint_v - height - -- synced - - else - - -- page_h_origin = 0 - -- page_v_origin = 0 - page_size_h = width - page_size_v = total - pos_r = getdirection(box) - pos_v = depth - pos_h = pos_r == righttoleft_code and width or 0 - - end - - shipbox_ref_h = pos_h - shipbox_ref_v = pos_v - - details = { - shippingmode = smode, -- target - boundingbox = { 0, 0, page_size_h, page_size_v }, - objectnumber = smode ~= "page" and objnum or nil, - pagenumber = smode == "page" and objnum or nil, - specification = specification, - } - - initialize(driver,details) - - lastfont = nil -- this forces a sync each page / object - - if getid(box) == vlist_code then - vlist_out(box,getlist(box)) - else - hlist_out(box,getlist(box)) - end - - ::DONE:: - - finalize(driver,details) - - shippingmode = "none" -end - --- This will move to back-out.lua eventually. - -do - - ----- sortedhash = table.sortedhash - - ----- tonut = nodes.tonut - local properties = nodes.properties.data - local flush = texio.write_nl - - local periods = utilities.strings.newrepeater(".") - - local function showdetails(n,l) - local p = properties[tonut(n)] - if p then - local done = false - for k, v in sortedhash(p) do - if done then - flush("\n") - else - done = true - end - flush(periods[l+1] .. " " .. k .. " = " .. tostring(v)) - end - end - end - - local whatsittracers = { - latelua = showdetails, - literal = showdetails, - } - - callback.register("show_whatsit",function(n,l) - local s = nodes.whatsitcodes[n.subtype] - texio.write(" [" .. s .. "]") - local w = whatsittracers[s] - if w then - w(n,l) - end - end) - -end diff --git a/tex/context/base/mkiv/driv-shp.mkxl b/tex/context/base/mkiv/driv-shp.mkxl index 68b62c72a..199215a59 100644 --- a/tex/context/base/mkiv/driv-shp.mkxl +++ b/tex/context/base/mkiv/driv-shp.mkxl @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\registerctxluafile{driv-shp}{optimize} +\registerctxluafile{driv-shp}{autosuffix,optimize} \unprotect diff --git a/tex/context/base/mkiv/font-con.lua b/tex/context/base/mkiv/font-con.lua index 6f4abe111..495148341 100644 --- a/tex/context/base/mkiv/font-con.lua +++ b/tex/context/base/mkiv/font-con.lua @@ -566,6 +566,15 @@ function constructors.scale(tfmdata,specification) targetparameters.quad = targetquad targetparameters.extra_space = targetextra_space -- + local hshift = parameters.hshift + if hshift then + targetparameters.hshift = delta * hshift + end + local vshift = parameters.vshift + if vshift then + targetparameters.vshift = delta * vshift + end + -- local ascender = parameters.ascender if ascender then targetparameters.ascender = delta * ascender diff --git a/tex/context/base/mkiv/font-imp-effects.lua b/tex/context/base/mkiv/font-imp-effects.lua index cc6e4c0bf..bd6cce879 100644 --- a/tex/context/base/mkiv/font-imp-effects.lua +++ b/tex/context/base/mkiv/font-imp-effects.lua @@ -280,6 +280,9 @@ end -- local show_effect = { "lua", "print('!')" } +----- shiftmode = false -- test in mkiv and lmtx +local shiftmode = CONTEXTLMTXMODE > 0 + local function manipulateeffect(tfmdata) local effect = tfmdata.properties.effect if effect then @@ -301,42 +304,49 @@ local function manipulateeffect(tfmdata) local factor = (1 + effect.factor) * factor local hfactor = (1 + effect.hfactor) * hfactor local vfactor = (1 + effect.vfactor) * vfactor - local vshift = vshift ~= 0 and upcommand[vshift] or false + if shiftmode then + parameters.hshift = hshift + parameters.vshift = vshift + else + vshift = vshift ~= 0 and upcommand[vshift] or false + hshift = rightcommand[hshift] + end for unicode, character in next, characters do local oldwidth = character.width local oldheight = character.height local olddepth = character.depth if oldwidth and oldwidth > 0 then character.width = oldwidth + wdelta - local commands = character.commands - local hshift = rightcommand[hshift] - if vshift then - if commands then - prependcommands ( commands, --- show_effect, - hshift, - vshift - ) - else - character.commands = { --- show_effect, - hshift, - vshift, - charcommand[unicode] - } - end - else - if commands then - prependcommands ( commands, --- show_effect, - hshift - ) + if not shiftmode then + local commands = character.commands + if vshift then + if commands then + prependcommands ( commands, + -- show_effect, + hshift, + vshift + ) + else + character.commands = { + -- show_effect, + hshift, + vshift, + charcommand[unicode] + } + end else - character.commands = { --- show_effect, - hshift, - charcommand[unicode] - } + if commands then + prependcommands ( commands, + -- show_effect, + hshift + ) + else + character.commands = { + -- show_effect, + hshift, + charcommand[unicode] + } + end end end end diff --git a/tex/context/base/mkiv/font-imp-tracing.lua b/tex/context/base/mkiv/font-imp-tracing.lua index 6ce445143..1acf14558 100644 --- a/tex/context/base/mkiv/font-imp-tracing.lua +++ b/tex/context/base/mkiv/font-imp-tracing.lua @@ -47,58 +47,22 @@ local v_none = variables.none -- boundingbox={yes|background|frame|empty|} -local bp = number.dimenfactors.bp -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) - local d = d * bp - local v = setmetatableindex(function(t,w) - local v = { "pdf", "origin", f_1(r,-d,w*bp,h+d) } - t[w] = v - return v - end) - t[d] = v - return v - end) - t[h] = v - return v -end) - -local forecache = setmetatableindex(function(t,h) - local h = h * bp - local v = setmetatableindex(function(t,d) - local d = d * bp - local v = setmetatableindex(function(t,w) - -- the frame goes through the boundingbox - local v = { "pdf", "origin", f_2(r,r/2,-d+r/2,w*bp-r,h+d-r) } - t[w] = v - return v - end) - t[d] = v - return v - end) - t[h] = v - return v -end) - -local startcolor = nil -local stopcolor = nil +local backgrounds = nil +local outlines = nil +local startcolor = nil +local stopcolor = nil local function initialize(tfmdata,key,value) if value then - if not backcolors then + if not backgrounds then local vfspecials = backends.pdf.tables.vfspecials - startcolor = vfspecials.startcolor - stopcolor = vfspecials.stopcolor + startcolor = vfspecials.startcolor + stopcolor = vfspecials.stopcolor + backgrounds = vfspecials.backgrounds + outlines = vfspecials.outlines end local characters = tfmdata.characters - local rulecache = backcache + local rulecache = backgrounds local showchar = true local color = "palegray" if type(value) == "string" then @@ -106,9 +70,9 @@ local function initialize(tfmdata,key,value) for i=1,#value do local v = value[i] if v == v_frame then - rulecache = forecache + rulecache = outlines elseif v == v_background then - rulecache = backcache + rulecache = backgrounds elseif v == v_empty then showchar = false elseif v == v_none then diff --git a/tex/context/base/mkiv/font-lib.mkvi b/tex/context/base/mkiv/font-lib.mkvi index 133143224..f4a20c8df 100644 --- a/tex/context/base/mkiv/font-lib.mkvi +++ b/tex/context/base/mkiv/font-lib.mkvi @@ -58,7 +58,7 @@ \registerctxluafile{font-ocm}{} \fi \else - \registerctxluafile{font-ogr}{} % lmtx + \registerctxluafile{font-ogr}{autosuffix} % lmtx \fi % we use otf code for type one diff --git a/tex/context/base/mkiv/font-ogr.lmt b/tex/context/base/mkiv/font-ogr.lmt new file mode 100644 index 000000000..94cf91494 --- /dev/null +++ b/tex/context/base/mkiv/font-ogr.lmt @@ -0,0 +1,672 @@ +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 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 diff --git a/tex/context/base/mkiv/font-otr.lua b/tex/context/base/mkiv/font-otr.lua index 119687f12..531f665de 100644 --- a/tex/context/base/mkiv/font-otr.lua +++ b/tex/context/base/mkiv/font-otr.lua @@ -2421,6 +2421,7 @@ function readers.loadfont(filename,n,instance) hascolor = fontdata.hascolor or false, instance = fontdata.instance, factors = fontdata.factors, + nofsubfonts = fontdata.subfonts and #fontdata.subfonts or nil, }, resources = { -- filename = fontdata.filename, diff --git a/tex/context/base/mkiv/grph-inc.lua b/tex/context/base/mkiv/grph-inc.lua index 508f3247a..6fdf74c08 100644 --- a/tex/context/base/mkiv/grph-inc.lua +++ b/tex/context/base/mkiv/grph-inc.lua @@ -703,9 +703,9 @@ implement { name = "figurestatus", actions = { get, context }, arguments = { " implement { name = "figurerequest", actions = { get, context }, arguments = { "'request'", "string", "string" } } implement { name = "figureused", actions = { get, context }, arguments = { "'used'", "string", "string" } } -implement { name = "figurefilepath", actions = { get, file.dirname, context }, arguments = { "'used'", "'fullname'" } } -implement { name = "figurefilename", actions = { get, file.nameonly, context }, arguments = { "'used'", "'fullname'" } } -implement { name = "figurefiletype", actions = { get, file.extname, context }, arguments = { "'used'", "'fullname'" } } +implement { name = "figurefilepath", public = true, actions = { get, file.dirname, context }, arguments = { "'used'", "'fullname'" } } +implement { name = "figurefilename", public = true, actions = { get, file.nameonly, context }, arguments = { "'used'", "'fullname'" } } +implement { name = "figurefiletype", public = true, actions = { get, file.extname, context }, arguments = { "'used'", "'fullname'" } } implement { name = "figuresetdimensions", actions = setdimensions, arguments = "integer" } diff --git a/tex/context/base/mkiv/grph-inc.mkiv b/tex/context/base/mkiv/grph-inc.mkiv index 578bad1d0..1b630de49 100644 --- a/tex/context/base/mkiv/grph-inc.mkiv +++ b/tex/context/base/mkiv/grph-inc.mkiv @@ -568,9 +568,9 @@ \def\figurefullname {\clf_figureused{fullname}{}} \def\noffigurepages {\clf_figureused{pages}{0}} -\def\figurefilepath {\clf_figurefilepath} -\def\figurefilename {\clf_figurefilename} -\def\figurefiletype {\clf_figurefiletype} +% \def\figurefilepath {\clf_figurefilepath} % public in lua +% \def\figurefilename {\clf_figurefilename} % public in lua +% \def\figurefiletype {\clf_figurefiletype} % public in lua \let\naturalfigurewidth \figurenaturalwidth \let\naturalfigureheight \figurenaturalheight diff --git a/tex/context/base/mkiv/libs-imp-curl.lmt b/tex/context/base/mkiv/libs-imp-curl.lmt new file mode 100644 index 000000000..b30739794 --- /dev/null +++ b/tex/context/base/mkiv/libs-imp-curl.lmt @@ -0,0 +1,296 @@ +if not modules then modules = { } end modules ['libs-imp-curl'] = { + version = 1.001, + comment = "companion to luat-lib.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/curl/libcurl.dll + +local libname = "curl" +local libfile = "libcurl" + +local curllib = resolvers.libraries.validoptional(libname) + +if not curllib then return end + +-- We're good, so we continue. + +local next, type = next, type +local lower, gsub = string.lower, string.gsub + +local mapping = { + ["acceptencoding"] = 102, + ["accepttimeoutms"] = 212, + ["addressscope"] = 171, + ["append"] = 50, + ["autoreferer"] = 58, + ["buffersize"] = 98, + ["cainfo"] = 65, + ["capath"] = 97, + ["certinfo"] = 172, + -- ["chunkbgnfunction"] = 198, + ["chunkdata"] = 201, + -- ["chunkendfunction"] = 199, + ["closepolicy"] = 72, + ["closesocketdata"] = 209, + -- ["closesocketfunction"] = 208, + ["connectonly"] = 141, + ["connecttimeout"] = 78, + ["connecttimeoutms"] = 156, + -- ["convfromnetworkfunction"] = 142, + -- ["convfromutf8function"] = 144, + -- ["convtonetworkfunction"] = 143, + ["cookie"] = 22, + ["cookiefile"] = 31, + ["cookiejar"] = 82, + ["cookielist"] = 135, + ["cookiesessionv"] = 96, + ["copypostfields"] = 165, + ["crlf"] = 27, + ["crlfile"] = 169, + ["customrequest"] = 36, + ["debugdata"] = 95, + -- ["debugfunction"] = 94, + ["dirlistonly"] = 48, + ["dnscachetimeout"] = 92, + ["dnsinterface"] = 221, + ["dnslocalip4"] = 222, + ["dnslocalip6"] = 223, + ["dnsservers"] = 211, + ["dnsuseglobalcache"] = 91, + ["egdsocket"] = 77, + ["errorbuffer"] = 10, + ["expect100timeoutms"] = 227, + ["failonerror"] = 45, + ["file"] = 1, + ["filetime"] = 69, + ["fnmatchdata"] = 202, + -- ["fnmatchfunction"] = 200, + ["followlocation"] = 52, + ["forbidreuse"] = 75, + ["freshconnect"] = 74, + ["ftpaccount"] = 134, + ["ftpalternativetouser"] = 147, + ["ftpcreatemissingdirs"] = 110, + ["ftpfilemethod"] = 138, + ["ftpresponsetimeout"] = 112, + ["ftpskippasvip"] = 137, + ["ftpsslccc"] = 154, + ["ftpuseeprt"] = 106, + ["ftpuseepsv"] = 85, + ["ftpusepret"] = 188, + ["ftpport"] = 17, + ["ftpsslauth"] = 129, + ["gssapidelegation"] = 210, + ["header"] = 42, + ["headerdata"] = 29, + -- ["headerfunction"] = 79, + ["http200aliases"] = 104, + ["httpcontentdecoding"] = 158, + ["httptransferdecoding"] = 157, + ["httpversion"] = 84, + ["httpauth"] = 107, + ["httpget"] = 80, + ["httpheader"] = 23, + ["httppost"] = 24, + ["httpproxytunnel"] = 61, + ["ignorecontentlength"] = 136, + ["infile"] = 9, + ["infilesize"] = 14, + ["infilesizelarge"] = 115, + ["interface"] = 62, + ["interleavedata"] = 195, + -- ["interleavefunction"] = 196, + ["ioctldata"] = 131, + -- ["ioctlfunction"] = 130, + ["ipresolve"] = 113, + ["issuercert"] = 170, + ["keypasswd"] = 26, + ["krblevel"] = 63, + ["localport"] = 139, + ["localportrange"] = 140, + ["loginoptions"] = 224, + ["lowspeedlimit"] = 19, + ["lowspeedtime"] = 20, + ["mailauth"] = 217, + ["mailfrom"] = 186, + ["mailrcpt"] = 187, + ["maxrecvspeedlarge"] = 146, + ["maxsendspeedlarge"] = 145, + ["maxconnects"] = 71, + ["maxfilesize"] = 114, + ["maxfilesizelarge"] = 117, + ["maxredirs"] = 68, + ["netrc"] = 51, + ["netrcfile"] = 118, + ["newdirectoryperms"] = 160, + ["newfileperms"] = 159, + ["nobody"] = 44, + ["noprogress"] = 43, + ["noproxy"] = 177, + ["nosignal"] = 99, + ["opensocketdata"] = 164, + -- ["opensocketfunction"] = 163, + ["password"] = 174, + ["port"] = 3, + ["post"] = 47, + -- ["postfields"] = 15, + -- ["postfieldsize"] = 60, + -- ["postfieldsizelarge"] = 120, + ["postquote"] = 39, + ["postredir"] = 161, + ["prequote"] = 93, + ["private"] = 103, + ["progressdata"] = 57, + -- ["progressfunction"] = 56, + ["protocols"] = 181, + ["proxy"] = 4, + ["proxytransfermode"] = 166, + ["proxyauth"] = 111, + ["proxypassword"] = 176, + ["proxyport"] = 59, + ["proxytype"] = 101, + ["proxyusername"] = 175, + ["proxyuserpwd"] = 6, + ["put"] = 54, + ["quote"] = 28, + ["randomfile"] = 76, + ["range"] = 7, + ["readdata"] = 9, + -- ["readfunction"] = 12, + ["redirprotocols"] = 182, + ["referer"] = 16, + ["resolve"] = 203, + ["resumefrom"] = 21, + ["resumefromlarge"] = 116, + ["rtspclientcseq"] = 193, + ["rtsprequest"] = 189, + ["rtspservercseq"] = 194, + ["rtspsessionid"] = 190, + ["rtspstreamuri"] = 191, + ["rtsptransport"] = 192, + ["rtspheader"] = 23, + ["saslir"] = 218, + ["seekdata"] = 168, + -- ["seekfunction"] = 167, + ["serverresponsetimeout"] = 112, + ["share"] = 100, + ["sockoptdata"] = 149, + -- ["sockoptfunction"] = 148, + ["socks5gssapinec"] = 180, + ["socks5gssapiservice"] = 179, + ["sshauthtypes"] = 151, + ["sshhostpublickeymd5"] = 162, + ["sshkeydata"] = 185, + -- ["sshkeyfunction"] = 184, + ["sshknownhosts"] = 183, + ["sshprivatekeyfile"] = 153, + ["sshpublickeyfile"] = 152, + ["sslcipherlist"] = 83, + ["sslctxdata"] = 109, + -- ["sslctxfunction"] = 108, + ["sslenablealpn"] = 226, + ["sslenablenpn"] = 225, + ["ssloptions"] = 216, + ["sslsessionidcache"] = 150, + ["sslverifyhost"] = 81, + ["sslverifypeer"] = 64, + ["sslcert"] = 25, + ["sslcerttype"] = 86, + ["sslengine"] = 89, + ["sslenginedefault"] = 90, + ["sslkey"] = 87, + ["sslkeytype"] = 88, + ["sslversion"] = 32, + ["stderr"] = 37, + ["tcpkeepalive"] = 213, + ["tcpkeepidle"] = 214, + ["tcpkeepintvl"] = 215, + ["tcpnodelay"] = 121, + ["telnetoptions"] = 70, + ["tftpblksize"] = 178, + ["timecondition"] = 33, + ["timeout"] = 13, + ["timeoutms"] = 155, + ["timevalue"] = 34, + ["tlsauthpassword"] = 205, + ["tlsauthtype"] = 206, + ["tlsauthusername"] = 204, + ["transferencoding"] = 207, + ["transfertext"] = 53, + ["unrestrictedauth"] = 105, + ["upload"] = 46, + ["url"] = 2, + ["usessl"] = 119, + ["useragent"] = 18, + ["username"] = 173, + ["userpwd"] = 5, + ["verbose"] = 41, + ["wildcardmatch"] = 197, + ["writedata"] = 1, + -- ["writefunction"] = 11, + ["writeheader"] = 29, + ["writeinfo"] = 40, + ["xferinfodata"] = 57, + -- ["xferinfofunction"] = 219, + ["xoauth2bearer"] = 220, +} + +table.setmetatableindex(mapping,function(t,k) + local s = gsub(lower(k),"[^a-z0-9]","") + local v = rawget(t,s) or false + t[k] = v + return v +end) + +local curl_fetch = curllib.fetch +local curl_escape = curllib.escape +local curl_unescape = curllib.unescape +local curl_getversion = curllib.getversion + +local report = logs.reporter(libname) + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local function fetch(options) + if okay() then + local t = type(options) + if t == "table" then + local o = { } + for name, value in next, options do + local index = mapping[name] + if index then + o[index] = value + end + end + return curl_fetch(o) + elseif t == "string" then + return curl_fetch { [mapping.url] = options } + else + report("invalid argument") + end + end +end + +local curl = { + getversion = function () return okay() and curl_getversion() end, + escape = function (s) return okay() and curl_escape (s) end, + unescape = function (s) return okay() and curl_unescape (s) end, + fetch = fetch, +} + +-- inspect(curl.fetch("http://www.pragma-ade.com/index.html")) +-- inspect(curl.fetch { url = "http://www.pragma-ade.com/index.html" }) + +package.loaded[libname] = curl + +return curl diff --git a/tex/context/base/mkiv/libs-imp-curl.lua b/tex/context/base/mkiv/libs-imp-curl.lua deleted file mode 100644 index b30739794..000000000 --- a/tex/context/base/mkiv/libs-imp-curl.lua +++ /dev/null @@ -1,296 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-curl'] = { - version = 1.001, - comment = "companion to luat-lib.mkxl", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/curl/libcurl.dll - -local libname = "curl" -local libfile = "libcurl" - -local curllib = resolvers.libraries.validoptional(libname) - -if not curllib then return end - --- We're good, so we continue. - -local next, type = next, type -local lower, gsub = string.lower, string.gsub - -local mapping = { - ["acceptencoding"] = 102, - ["accepttimeoutms"] = 212, - ["addressscope"] = 171, - ["append"] = 50, - ["autoreferer"] = 58, - ["buffersize"] = 98, - ["cainfo"] = 65, - ["capath"] = 97, - ["certinfo"] = 172, - -- ["chunkbgnfunction"] = 198, - ["chunkdata"] = 201, - -- ["chunkendfunction"] = 199, - ["closepolicy"] = 72, - ["closesocketdata"] = 209, - -- ["closesocketfunction"] = 208, - ["connectonly"] = 141, - ["connecttimeout"] = 78, - ["connecttimeoutms"] = 156, - -- ["convfromnetworkfunction"] = 142, - -- ["convfromutf8function"] = 144, - -- ["convtonetworkfunction"] = 143, - ["cookie"] = 22, - ["cookiefile"] = 31, - ["cookiejar"] = 82, - ["cookielist"] = 135, - ["cookiesessionv"] = 96, - ["copypostfields"] = 165, - ["crlf"] = 27, - ["crlfile"] = 169, - ["customrequest"] = 36, - ["debugdata"] = 95, - -- ["debugfunction"] = 94, - ["dirlistonly"] = 48, - ["dnscachetimeout"] = 92, - ["dnsinterface"] = 221, - ["dnslocalip4"] = 222, - ["dnslocalip6"] = 223, - ["dnsservers"] = 211, - ["dnsuseglobalcache"] = 91, - ["egdsocket"] = 77, - ["errorbuffer"] = 10, - ["expect100timeoutms"] = 227, - ["failonerror"] = 45, - ["file"] = 1, - ["filetime"] = 69, - ["fnmatchdata"] = 202, - -- ["fnmatchfunction"] = 200, - ["followlocation"] = 52, - ["forbidreuse"] = 75, - ["freshconnect"] = 74, - ["ftpaccount"] = 134, - ["ftpalternativetouser"] = 147, - ["ftpcreatemissingdirs"] = 110, - ["ftpfilemethod"] = 138, - ["ftpresponsetimeout"] = 112, - ["ftpskippasvip"] = 137, - ["ftpsslccc"] = 154, - ["ftpuseeprt"] = 106, - ["ftpuseepsv"] = 85, - ["ftpusepret"] = 188, - ["ftpport"] = 17, - ["ftpsslauth"] = 129, - ["gssapidelegation"] = 210, - ["header"] = 42, - ["headerdata"] = 29, - -- ["headerfunction"] = 79, - ["http200aliases"] = 104, - ["httpcontentdecoding"] = 158, - ["httptransferdecoding"] = 157, - ["httpversion"] = 84, - ["httpauth"] = 107, - ["httpget"] = 80, - ["httpheader"] = 23, - ["httppost"] = 24, - ["httpproxytunnel"] = 61, - ["ignorecontentlength"] = 136, - ["infile"] = 9, - ["infilesize"] = 14, - ["infilesizelarge"] = 115, - ["interface"] = 62, - ["interleavedata"] = 195, - -- ["interleavefunction"] = 196, - ["ioctldata"] = 131, - -- ["ioctlfunction"] = 130, - ["ipresolve"] = 113, - ["issuercert"] = 170, - ["keypasswd"] = 26, - ["krblevel"] = 63, - ["localport"] = 139, - ["localportrange"] = 140, - ["loginoptions"] = 224, - ["lowspeedlimit"] = 19, - ["lowspeedtime"] = 20, - ["mailauth"] = 217, - ["mailfrom"] = 186, - ["mailrcpt"] = 187, - ["maxrecvspeedlarge"] = 146, - ["maxsendspeedlarge"] = 145, - ["maxconnects"] = 71, - ["maxfilesize"] = 114, - ["maxfilesizelarge"] = 117, - ["maxredirs"] = 68, - ["netrc"] = 51, - ["netrcfile"] = 118, - ["newdirectoryperms"] = 160, - ["newfileperms"] = 159, - ["nobody"] = 44, - ["noprogress"] = 43, - ["noproxy"] = 177, - ["nosignal"] = 99, - ["opensocketdata"] = 164, - -- ["opensocketfunction"] = 163, - ["password"] = 174, - ["port"] = 3, - ["post"] = 47, - -- ["postfields"] = 15, - -- ["postfieldsize"] = 60, - -- ["postfieldsizelarge"] = 120, - ["postquote"] = 39, - ["postredir"] = 161, - ["prequote"] = 93, - ["private"] = 103, - ["progressdata"] = 57, - -- ["progressfunction"] = 56, - ["protocols"] = 181, - ["proxy"] = 4, - ["proxytransfermode"] = 166, - ["proxyauth"] = 111, - ["proxypassword"] = 176, - ["proxyport"] = 59, - ["proxytype"] = 101, - ["proxyusername"] = 175, - ["proxyuserpwd"] = 6, - ["put"] = 54, - ["quote"] = 28, - ["randomfile"] = 76, - ["range"] = 7, - ["readdata"] = 9, - -- ["readfunction"] = 12, - ["redirprotocols"] = 182, - ["referer"] = 16, - ["resolve"] = 203, - ["resumefrom"] = 21, - ["resumefromlarge"] = 116, - ["rtspclientcseq"] = 193, - ["rtsprequest"] = 189, - ["rtspservercseq"] = 194, - ["rtspsessionid"] = 190, - ["rtspstreamuri"] = 191, - ["rtsptransport"] = 192, - ["rtspheader"] = 23, - ["saslir"] = 218, - ["seekdata"] = 168, - -- ["seekfunction"] = 167, - ["serverresponsetimeout"] = 112, - ["share"] = 100, - ["sockoptdata"] = 149, - -- ["sockoptfunction"] = 148, - ["socks5gssapinec"] = 180, - ["socks5gssapiservice"] = 179, - ["sshauthtypes"] = 151, - ["sshhostpublickeymd5"] = 162, - ["sshkeydata"] = 185, - -- ["sshkeyfunction"] = 184, - ["sshknownhosts"] = 183, - ["sshprivatekeyfile"] = 153, - ["sshpublickeyfile"] = 152, - ["sslcipherlist"] = 83, - ["sslctxdata"] = 109, - -- ["sslctxfunction"] = 108, - ["sslenablealpn"] = 226, - ["sslenablenpn"] = 225, - ["ssloptions"] = 216, - ["sslsessionidcache"] = 150, - ["sslverifyhost"] = 81, - ["sslverifypeer"] = 64, - ["sslcert"] = 25, - ["sslcerttype"] = 86, - ["sslengine"] = 89, - ["sslenginedefault"] = 90, - ["sslkey"] = 87, - ["sslkeytype"] = 88, - ["sslversion"] = 32, - ["stderr"] = 37, - ["tcpkeepalive"] = 213, - ["tcpkeepidle"] = 214, - ["tcpkeepintvl"] = 215, - ["tcpnodelay"] = 121, - ["telnetoptions"] = 70, - ["tftpblksize"] = 178, - ["timecondition"] = 33, - ["timeout"] = 13, - ["timeoutms"] = 155, - ["timevalue"] = 34, - ["tlsauthpassword"] = 205, - ["tlsauthtype"] = 206, - ["tlsauthusername"] = 204, - ["transferencoding"] = 207, - ["transfertext"] = 53, - ["unrestrictedauth"] = 105, - ["upload"] = 46, - ["url"] = 2, - ["usessl"] = 119, - ["useragent"] = 18, - ["username"] = 173, - ["userpwd"] = 5, - ["verbose"] = 41, - ["wildcardmatch"] = 197, - ["writedata"] = 1, - -- ["writefunction"] = 11, - ["writeheader"] = 29, - ["writeinfo"] = 40, - ["xferinfodata"] = 57, - -- ["xferinfofunction"] = 219, - ["xoauth2bearer"] = 220, -} - -table.setmetatableindex(mapping,function(t,k) - local s = gsub(lower(k),"[^a-z0-9]","") - local v = rawget(t,s) or false - t[k] = v - return v -end) - -local curl_fetch = curllib.fetch -local curl_escape = curllib.escape -local curl_unescape = curllib.unescape -local curl_getversion = curllib.getversion - -local report = logs.reporter(libname) - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local function fetch(options) - if okay() then - local t = type(options) - if t == "table" then - local o = { } - for name, value in next, options do - local index = mapping[name] - if index then - o[index] = value - end - end - return curl_fetch(o) - elseif t == "string" then - return curl_fetch { [mapping.url] = options } - else - report("invalid argument") - end - end -end - -local curl = { - getversion = function () return okay() and curl_getversion() end, - escape = function (s) return okay() and curl_escape (s) end, - unescape = function (s) return okay() and curl_unescape (s) end, - fetch = fetch, -} - --- inspect(curl.fetch("http://www.pragma-ade.com/index.html")) --- inspect(curl.fetch { url = "http://www.pragma-ade.com/index.html" }) - -package.loaded[libname] = curl - -return curl diff --git a/tex/context/base/mkiv/libs-imp-ghostscript.lmt b/tex/context/base/mkiv/libs-imp-ghostscript.lmt new file mode 100644 index 000000000..b129a58c1 --- /dev/null +++ b/tex/context/base/mkiv/libs-imp-ghostscript.lmt @@ -0,0 +1,111 @@ +if not modules then modules = { } end modules ['libs-imp-ghostscript'] = { + version = 1.001, + comment = "companion to luat-lib.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", +} + +local libname = "ghostscript" +local libfile = "gsdll64" -- what on unix? + +local gslib = resolvers.libraries.validoptional(libname) + +if not gslib then return end + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local insert = table.insert +local formatters = string.formatters + +local ghostscript = utilities.ghostscript or { } +utilities.ghostscript = ghostscript + +local gs_execute = gslib.execute +local nofruns = 0 +local report = logs.reporter(libname) + +function ghostscript.convert(specification) + if okay() then + -- + nofruns = nofruns + 1 + statistics.starttiming(ghostscript) + -- + local inputname = specification.inputname + if not inputname or inputname == "" then + report("invalid run %s, no inputname specified",nofruns) + statistics.stoptiming(ghostscript) + return false + end + local outputname = specification.outputname + if not outputname or outputname == "" then + outputname = file.replacesuffix(inputname,"pdf") + end + -- + if not lfs.isfile(inputname) then + report("invalid run %s, input file %a is not found",nofruns,inputname) + statistics.stoptiming(ghostscript) + return false + end + -- + local device = specification.device + if not device or device == "" then + device = "pdfwrite" + end + -- + local code = specification.code + if not code or code == "" then + code = ".setpdfwrite" + end + -- + local options = specification.options or { } + -- + insert(options,"-dNOPAUSE") + insert(options,"-dBATCH") + insert(options,"-dSAFER") + insert(options,formatters["-sDEVICE=%s"](device)) + insert(options,formatters["-sOutputFile=%s"](outputname)) + insert(options,"-c") + insert(options,code) + insert(options,"-f") + insert(options,inputname) + -- + report("run %s, input file %a, outputfile %a",nofruns,inputname,outputname) + report("") + local done = gslib_execute(options) + report("") + -- + statistics.stoptiming(ghostscript) + if done then + return outputname + else + report("run %s quit with errors",nofruns) + return false + end + end +end + +function ghostscript.statistics(report) + local runtime = statistics.elapsedtime(ghostscript) + if report then + report("nofruns %s, runtime %s",nofruns,runtime) + else + return { + runtime = runtime, + nofruns = nofruns, + } + end +end + +-- for i=1,100 do +-- ghostscript.convert { inputname = "temp.eps" } +-- ghostscript.convert { inputname = "t:/escrito/tiger.eps" } +-- end +-- ghostscript.statistics(true) diff --git a/tex/context/base/mkiv/libs-imp-ghostscript.lua b/tex/context/base/mkiv/libs-imp-ghostscript.lua deleted file mode 100644 index b129a58c1..000000000 --- a/tex/context/base/mkiv/libs-imp-ghostscript.lua +++ /dev/null @@ -1,111 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-ghostscript'] = { - version = 1.001, - comment = "companion to luat-lib.mkxl", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files", -} - -local libname = "ghostscript" -local libfile = "gsdll64" -- what on unix? - -local gslib = resolvers.libraries.validoptional(libname) - -if not gslib then return end - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local insert = table.insert -local formatters = string.formatters - -local ghostscript = utilities.ghostscript or { } -utilities.ghostscript = ghostscript - -local gs_execute = gslib.execute -local nofruns = 0 -local report = logs.reporter(libname) - -function ghostscript.convert(specification) - if okay() then - -- - nofruns = nofruns + 1 - statistics.starttiming(ghostscript) - -- - local inputname = specification.inputname - if not inputname or inputname == "" then - report("invalid run %s, no inputname specified",nofruns) - statistics.stoptiming(ghostscript) - return false - end - local outputname = specification.outputname - if not outputname or outputname == "" then - outputname = file.replacesuffix(inputname,"pdf") - end - -- - if not lfs.isfile(inputname) then - report("invalid run %s, input file %a is not found",nofruns,inputname) - statistics.stoptiming(ghostscript) - return false - end - -- - local device = specification.device - if not device or device == "" then - device = "pdfwrite" - end - -- - local code = specification.code - if not code or code == "" then - code = ".setpdfwrite" - end - -- - local options = specification.options or { } - -- - insert(options,"-dNOPAUSE") - insert(options,"-dBATCH") - insert(options,"-dSAFER") - insert(options,formatters["-sDEVICE=%s"](device)) - insert(options,formatters["-sOutputFile=%s"](outputname)) - insert(options,"-c") - insert(options,code) - insert(options,"-f") - insert(options,inputname) - -- - report("run %s, input file %a, outputfile %a",nofruns,inputname,outputname) - report("") - local done = gslib_execute(options) - report("") - -- - statistics.stoptiming(ghostscript) - if done then - return outputname - else - report("run %s quit with errors",nofruns) - return false - end - end -end - -function ghostscript.statistics(report) - local runtime = statistics.elapsedtime(ghostscript) - if report then - report("nofruns %s, runtime %s",nofruns,runtime) - else - return { - runtime = runtime, - nofruns = nofruns, - } - end -end - --- for i=1,100 do --- ghostscript.convert { inputname = "temp.eps" } --- ghostscript.convert { inputname = "t:/escrito/tiger.eps" } --- end --- ghostscript.statistics(true) diff --git a/tex/context/base/mkiv/libs-imp-graphicsmagick.lmt b/tex/context/base/mkiv/libs-imp-graphicsmagick.lmt new file mode 100644 index 000000000..6f5d1d967 --- /dev/null +++ b/tex/context/base/mkiv/libs-imp-graphicsmagick.lmt @@ -0,0 +1,77 @@ +if not modules then modules = { } end modules ['libs-imp-graphicsmagick'] = { + version = 1.001, + comment = "companion to luat-lib.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", +} + +local libname = "graphicsmagick" +local libfile = { "CORE_RL_magick_", "CORE_RL_wand_" } + +local gmlib = resolvers.libraries.validoptional(libname) + +if not gmlib then return end + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local graphicsmagick = utilities.graphicsmagick or { } +utilities.graphicsmagick = graphicsmagick +utilities.graphicmagick = graphicsmagick + +local gm_execute = gmlib.execute +local nofruns = 0 +local report = logs.reporter(libname) + +function graphicsmagick.convert(specification) + if okay() then + -- + nofruns = nofruns + 1 + statistics.starttiming(graphicsmagick) + -- + local inputname = specification.inputname + if not inputname or inputname == "" then + report("invalid run %s, no inputname specified",nofruns) + statistics.stoptiming(graphicsmagick) + return false + end + local outputname = specification.outputname + if not outputname or outputname == "" then + outputname = file.replacesuffix(inputname,"pdf") + end + -- + if not lfs.isfile(inputname) then + report("invalid run %s, input file %a is not found",nofruns,inputname) + statistics.stoptiming(graphicsmagick) + return false + end + -- + report("run %s, input file %a, outputfile %a",nofruns,inputname,outputname) + -- + gm_execute { inputfile = inputname, outputfile = outputname } + -- + statistics.stoptiming(graphicsmagick) + end +end + +function graphicsmagick.statistics(report) + local runtime = statistics.elapsedtime(graphicsmagick) + if report then + report("nofruns %s, runtime %s",nofruns,runtime) + else + return { + runtime = runtime, + nofruns = nofruns, + } + end +end + +-- graphicsmagick.convert { inputname = "t:/sources/hacker.jpg", outputname = "e:/tmp/hacker.png" } +-- graphicsmagick.statistics(true) diff --git a/tex/context/base/mkiv/libs-imp-graphicsmagick.lua b/tex/context/base/mkiv/libs-imp-graphicsmagick.lua deleted file mode 100644 index 6f5d1d967..000000000 --- a/tex/context/base/mkiv/libs-imp-graphicsmagick.lua +++ /dev/null @@ -1,77 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-graphicsmagick'] = { - version = 1.001, - comment = "companion to luat-lib.mkxl", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files", -} - -local libname = "graphicsmagick" -local libfile = { "CORE_RL_magick_", "CORE_RL_wand_" } - -local gmlib = resolvers.libraries.validoptional(libname) - -if not gmlib then return end - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local graphicsmagick = utilities.graphicsmagick or { } -utilities.graphicsmagick = graphicsmagick -utilities.graphicmagick = graphicsmagick - -local gm_execute = gmlib.execute -local nofruns = 0 -local report = logs.reporter(libname) - -function graphicsmagick.convert(specification) - if okay() then - -- - nofruns = nofruns + 1 - statistics.starttiming(graphicsmagick) - -- - local inputname = specification.inputname - if not inputname or inputname == "" then - report("invalid run %s, no inputname specified",nofruns) - statistics.stoptiming(graphicsmagick) - return false - end - local outputname = specification.outputname - if not outputname or outputname == "" then - outputname = file.replacesuffix(inputname,"pdf") - end - -- - if not lfs.isfile(inputname) then - report("invalid run %s, input file %a is not found",nofruns,inputname) - statistics.stoptiming(graphicsmagick) - return false - end - -- - report("run %s, input file %a, outputfile %a",nofruns,inputname,outputname) - -- - gm_execute { inputfile = inputname, outputfile = outputname } - -- - statistics.stoptiming(graphicsmagick) - end -end - -function graphicsmagick.statistics(report) - local runtime = statistics.elapsedtime(graphicsmagick) - if report then - report("nofruns %s, runtime %s",nofruns,runtime) - else - return { - runtime = runtime, - nofruns = nofruns, - } - end -end - --- graphicsmagick.convert { inputname = "t:/sources/hacker.jpg", outputname = "e:/tmp/hacker.png" } --- graphicsmagick.statistics(true) diff --git a/tex/context/base/mkiv/libs-imp-kpse.lmt b/tex/context/base/mkiv/libs-imp-kpse.lmt new file mode 100644 index 000000000..f8e4a9907 --- /dev/null +++ b/tex/context/base/mkiv/libs-imp-kpse.lmt @@ -0,0 +1,58 @@ +if not modules then modules = { } end modules ['libs-imp-kpse'] = { + version = 1.001, + comment = "companion to luat-imp-kpse.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is an experiment. It might make sense to have this available in case I want +-- more runners to use LuaMetaTeX in which case (as with mtxrun using LuaTeX) we +-- need to load kpse. + +local libname = "kpse" +local libfile = (os.platform == "win64" and "kpathsea*w64") + or (os.platform == "win32" and "kpathsea*w32") + or "libkpathsea" +local libkpse = resolvers.libraries.validoptional(libname) + +if package.loaded[libname] then + return package.loaded[libname] +end + +-- This is a variant that loaded directly: + +-- kpse = libkpse -- the library will issue warnings anyway +-- +-- resolvers.libraries.optionalloaded(libname,libfile) -- no need to chedk if true + +-- This variant delays loading and has a bit more protection: + +local function okay() + if libkpse and resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local kpse = { } + +for k, v in next, libkpse do + kpse[k] = function(...) if okay() then return v(...) end end +end + +-- We properly register the module: + +package.loaded[libname] = kpse + +optional.loaded.kpse = kpse + +-- A simple test: + +-- kpse.set_program_name("pdftex") +-- print("find file:",kpse.find_file("oeps.tex")) +-- print("find file:",kpse.find_file("context.mkii")) + +return kpse diff --git a/tex/context/base/mkiv/libs-imp-kpse.lua b/tex/context/base/mkiv/libs-imp-kpse.lua deleted file mode 100644 index f8e4a9907..000000000 --- a/tex/context/base/mkiv/libs-imp-kpse.lua +++ /dev/null @@ -1,58 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-kpse'] = { - version = 1.001, - comment = "companion to luat-imp-kpse.mkxl", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- This is an experiment. It might make sense to have this available in case I want --- more runners to use LuaMetaTeX in which case (as with mtxrun using LuaTeX) we --- need to load kpse. - -local libname = "kpse" -local libfile = (os.platform == "win64" and "kpathsea*w64") - or (os.platform == "win32" and "kpathsea*w32") - or "libkpathsea" -local libkpse = resolvers.libraries.validoptional(libname) - -if package.loaded[libname] then - return package.loaded[libname] -end - --- This is a variant that loaded directly: - --- kpse = libkpse -- the library will issue warnings anyway --- --- resolvers.libraries.optionalloaded(libname,libfile) -- no need to chedk if true - --- This variant delays loading and has a bit more protection: - -local function okay() - if libkpse and resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local kpse = { } - -for k, v in next, libkpse do - kpse[k] = function(...) if okay() then return v(...) end end -end - --- We properly register the module: - -package.loaded[libname] = kpse - -optional.loaded.kpse = kpse - --- A simple test: - --- kpse.set_program_name("pdftex") --- print("find file:",kpse.find_file("oeps.tex")) --- print("find file:",kpse.find_file("context.mkii")) - -return kpse diff --git a/tex/context/base/mkiv/libs-imp-kpse.mkxl b/tex/context/base/mkiv/libs-imp-kpse.mkxl index 8a3d7826f..f76c99029 100644 --- a/tex/context/base/mkiv/libs-imp-kpse.mkxl +++ b/tex/context/base/mkiv/libs-imp-kpse.mkxl @@ -15,7 +15,7 @@ %D know when it comes in handy; probably never in a real run, but I might want to %D make a \LUAMETATEX\ plain format one day, just for the fun of it. -% \registerctxluafile{libs-imp-kpse}{} +% \registerctxluafile{libs-imp-kpse}{autosuffix} \continueifinputfile{libs-imp-kpse.mkxl} diff --git a/tex/context/base/mkiv/libs-imp-mujs.lmt b/tex/context/base/mkiv/libs-imp-mujs.lmt new file mode 100644 index 000000000..264c8e531 --- /dev/null +++ b/tex/context/base/mkiv/libs-imp-mujs.lmt @@ -0,0 +1,126 @@ +if not modules then modules = { } end modules ['libs-imp-mujs'] = { + version = 1.001, + comment = "companion to luat-imp-mujs.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is an experiment. When a new user knows \JAVASCRIPT\ it can be a +-- stepping stone to using \LUA. + +-- local ecmascript = optional.mujs.initialize("libmujs") +-- local execute = optional.mujs.execute + +local libname = "mujs" +local libfile = "libmujs" + +if package.loaded[libname] then + return package.loaded[libname] +end + +local mujslib = resolvers.libraries.validoptional(libname) + +if not mujslib then + return +end + +local files = { } +local openfile = io.open +local findfile = resolvers.findfile + +local mujs_execute = mujslib.execute +local mujs_dofile = mujslib.dofile +local mujs_reset = mujslib.reset + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + mujs_execute( + "var catcodes = { " .. + "'tex': " .. tex.texcatcodes .. "," .. + "'ctx': " .. tex.ctxcatcodes .. "," .. + "'prt': " .. tex.prtcatcodes .. "," .. + "'vrb': " .. tex.vrbcatcodes .. "," .. + "};" + ) + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +mujslib.setfindfile(findfile) + +mujslib.setopenfile(function(name) + local full = findfile(name) + if full then + local f = openfile(full,"rb") + if f then + for i=1,100 do + if not files[i] then + files[i] = f + return i + end + end + end + end +end) + +mujslib.setclosefile(function(id) + local f = files[id] + if f then + f:close() + files[id] = false + end +end) + +mujslib.setreadfile(function(id,how) + local f = files[id] + if f then + return (f:read(how or "*l")) + end +end) + +mujslib.setseekfile(function(id,whence,offset) + local f = files[id] + if f then + return (f:seek(whence,offset)) + end +end) + +local reporters = { + console = logs.reporter("mujs","console"), + report = logs.reporter("mujs","report"), +} + +mujslib.setconsole(function(category,name) + reporters[category](name) +end) + +local mujs = { + ["execute"] = function(c,s) if okay() then mujs_execute(c,s) end end, + ["dofile"] = function(n) if okay() then mujs_dofile(n) end end, + ["reset"] = function(n) if okay() then mujs_reset(n) end end, +} + +package.loaded[libname] = mujs + +optional.loaded.mujs = mujs + +interfaces.implement { + name = "ecmacode", + actions = mujs.execute, + arguments = "string", + public = true, +} + +interfaces.implement { + name = "ecmafile", + actions = mujs.dofile, + arguments = "string", + public = true, + protected = true, +} + +return mujs diff --git a/tex/context/base/mkiv/libs-imp-mujs.lua b/tex/context/base/mkiv/libs-imp-mujs.lua deleted file mode 100644 index 264c8e531..000000000 --- a/tex/context/base/mkiv/libs-imp-mujs.lua +++ /dev/null @@ -1,126 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-mujs'] = { - version = 1.001, - comment = "companion to luat-imp-mujs.mkxl", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- This is an experiment. When a new user knows \JAVASCRIPT\ it can be a --- stepping stone to using \LUA. - --- local ecmascript = optional.mujs.initialize("libmujs") --- local execute = optional.mujs.execute - -local libname = "mujs" -local libfile = "libmujs" - -if package.loaded[libname] then - return package.loaded[libname] -end - -local mujslib = resolvers.libraries.validoptional(libname) - -if not mujslib then - return -end - -local files = { } -local openfile = io.open -local findfile = resolvers.findfile - -local mujs_execute = mujslib.execute -local mujs_dofile = mujslib.dofile -local mujs_reset = mujslib.reset - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - mujs_execute( - "var catcodes = { " .. - "'tex': " .. tex.texcatcodes .. "," .. - "'ctx': " .. tex.ctxcatcodes .. "," .. - "'prt': " .. tex.prtcatcodes .. "," .. - "'vrb': " .. tex.vrbcatcodes .. "," .. - "};" - ) - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -mujslib.setfindfile(findfile) - -mujslib.setopenfile(function(name) - local full = findfile(name) - if full then - local f = openfile(full,"rb") - if f then - for i=1,100 do - if not files[i] then - files[i] = f - return i - end - end - end - end -end) - -mujslib.setclosefile(function(id) - local f = files[id] - if f then - f:close() - files[id] = false - end -end) - -mujslib.setreadfile(function(id,how) - local f = files[id] - if f then - return (f:read(how or "*l")) - end -end) - -mujslib.setseekfile(function(id,whence,offset) - local f = files[id] - if f then - return (f:seek(whence,offset)) - end -end) - -local reporters = { - console = logs.reporter("mujs","console"), - report = logs.reporter("mujs","report"), -} - -mujslib.setconsole(function(category,name) - reporters[category](name) -end) - -local mujs = { - ["execute"] = function(c,s) if okay() then mujs_execute(c,s) end end, - ["dofile"] = function(n) if okay() then mujs_dofile(n) end end, - ["reset"] = function(n) if okay() then mujs_reset(n) end end, -} - -package.loaded[libname] = mujs - -optional.loaded.mujs = mujs - -interfaces.implement { - name = "ecmacode", - actions = mujs.execute, - arguments = "string", - public = true, -} - -interfaces.implement { - name = "ecmafile", - actions = mujs.dofile, - arguments = "string", - public = true, - protected = true, -} - -return mujs diff --git a/tex/context/base/mkiv/libs-imp-mujs.mkxl b/tex/context/base/mkiv/libs-imp-mujs.mkxl index 3fc9d9124..a8fe5801f 100644 --- a/tex/context/base/mkiv/libs-imp-mujs.mkxl +++ b/tex/context/base/mkiv/libs-imp-mujs.mkxl @@ -21,7 +21,7 @@ \expandafter \endinput \fi -\registerctxluafile{libs-imp-mujs}{} +\registerctxluafile{libs-imp-mujs}{autosuffix} \unprotect diff --git a/tex/context/base/mkiv/libs-imp-mysql.lmt b/tex/context/base/mkiv/libs-imp-mysql.lmt new file mode 100644 index 000000000..3e938a6de --- /dev/null +++ b/tex/context/base/mkiv/libs-imp-mysql.lmt @@ -0,0 +1,220 @@ +if not modules then modules = { } end modules ['libs-imp-mysql'] = { + version = 1.001, + comment = "companion to util-sql.lua", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/mysql/libmysql.dll + +local libname = "mysql" +local libfile = "libmysql" + +local mysqllib = resolvers.libraries.validoptional(libname) + +if not mysqllib then return end + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local lpegmatch = lpeg.match +local setmetatable = setmetatable + +local sql = utilities.sql or require("util-sql") +local report = logs.reporter(libname) + +local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end) +local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end) + +local mysql_open = mysqllib.open +local mysql_close = mysqllib.close +local mysql_execute = mysqllib.execute +local mysql_getmessage = mysqllib.getmessage + +local helpers = sql.helpers +local methods = sql.methods +local validspecification = helpers.validspecification +local preparetemplate = helpers.preparetemplate +local querysplitter = helpers.querysplitter +local cache = { } +local timeout -- = 3600 -- to be tested + +local function connect(specification) + local db = mysql_open( + specification.database or "", + specification.username or "", + specification.password or "", + specification.host or "", + specification.port + ) + if db and timeout then + mysql_execute(db,formatters["SET SESSION connect_timeout=%s ;"](timeout)) + end + return db +end + +local function execute_once(specification,retry) + if okay() then + if trace_sql then + report("executing mysql") + end + if not validspecification(specification) then + report("error in specification") + end + local query = preparetemplate(specification) + if not query then + report("error in preparation") + return + else + query = lpegmatch(querysplitter,query) + end + local base = specification.database -- or specification.presets and specification.presets.database + if not base then + report("no database specified") + return + end + local result = { } + local keys = { } + local id = specification.id + local db = nil + if id then + local session = cache[id] + if session then + db = session.db + else + db = connect(specification) + if not db then + report("no session database specified") + else + cache[id] = { + specification = specification, + db = db, + } + end + end + else + db = connect(specification) + end + if not db then + report("no database opened") + else + local converter = specification.converter + local nofrows = 0 + local callback = nil + if converter then + local convert = converter.mysql + callback = function(nofcolumns,values,fields) + nofrows = nofrows + 1 + result[nofrows] = convert(values) + end + else + callback = function(nofcolumns,values,fields) + local column = { } + for i=1,nofcolumns do + local field + if fields then + field = fields[i] + keys[i] = field + else + field = keys[i] + end + if field then + column[field] = values[i] + end + end + nofrows = nofrows + 1 + result[nofrows] = column + end + end + for i=1,#query do + local okay = mysql_execute(db,query[i],callback) + if not okay then + if id and retry and i == 1 then + report("error: %s, retrying to connect",mysql_getmessage(db)) + mysql_close(db) + cache[id] = nil + return execute_once(specification,false) + else + report("error: %s",mysql_getmessage(db)) + end + end + end + end + if db and not id then + mysql_close(db) + end + -- bonus + local one = result[1] + if one then + setmetatable(result,{ __index = one } ) + end + -- + return result, keys + else + report("error: ","no library loaded") + end +end + +local function execute(specification) + return execute_once(specification,true) +end + +-- Here we build the dataset stepwise so we don't use the data hack that +-- is used in the client variant. + +local wraptemplate = [[ +local converters = utilities.sql.converters +local deserialize = utilities.sql.deserialize + +local tostring = tostring +local tonumber = tonumber +local booleanstring = string.booleanstring + +%s + +return function(cells) + -- %s (not needed) + -- %s (not needed) + return { + %s + } +end +]] + +-- return function(result) +-- if not result then +-- return { } +-- end +-- local nofrows = #result +-- if nofrows == 0 then +-- return { } +-- end +-- local target = { } -- no %s needed here +-- for i=1,nofrows do +-- target[%s] = { +-- %s +-- } +-- end +-- return result +-- end + +local celltemplate = "cells[%s]" + +methods.mysql = { + execute = execute, + usesfiles = false, + wraptemplate = wraptemplate, + celltemplate = celltemplate, +} + +package.loaded["util-sql-imp-ffi"] = methods.mysql +package.loaded["util-sql-imp-mysql"] = methods.mysql +package.loaded["util-sql-imp-library"] = methods.mysql +package.loaded[libname] = methods.mysql diff --git a/tex/context/base/mkiv/libs-imp-mysql.lua b/tex/context/base/mkiv/libs-imp-mysql.lua deleted file mode 100644 index 3e938a6de..000000000 --- a/tex/context/base/mkiv/libs-imp-mysql.lua +++ /dev/null @@ -1,220 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-mysql'] = { - version = 1.001, - comment = "companion to util-sql.lua", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/mysql/libmysql.dll - -local libname = "mysql" -local libfile = "libmysql" - -local mysqllib = resolvers.libraries.validoptional(libname) - -if not mysqllib then return end - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local lpegmatch = lpeg.match -local setmetatable = setmetatable - -local sql = utilities.sql or require("util-sql") -local report = logs.reporter(libname) - -local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end) -local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end) - -local mysql_open = mysqllib.open -local mysql_close = mysqllib.close -local mysql_execute = mysqllib.execute -local mysql_getmessage = mysqllib.getmessage - -local helpers = sql.helpers -local methods = sql.methods -local validspecification = helpers.validspecification -local preparetemplate = helpers.preparetemplate -local querysplitter = helpers.querysplitter -local cache = { } -local timeout -- = 3600 -- to be tested - -local function connect(specification) - local db = mysql_open( - specification.database or "", - specification.username or "", - specification.password or "", - specification.host or "", - specification.port - ) - if db and timeout then - mysql_execute(db,formatters["SET SESSION connect_timeout=%s ;"](timeout)) - end - return db -end - -local function execute_once(specification,retry) - if okay() then - if trace_sql then - report("executing mysql") - end - if not validspecification(specification) then - report("error in specification") - end - local query = preparetemplate(specification) - if not query then - report("error in preparation") - return - else - query = lpegmatch(querysplitter,query) - end - local base = specification.database -- or specification.presets and specification.presets.database - if not base then - report("no database specified") - return - end - local result = { } - local keys = { } - local id = specification.id - local db = nil - if id then - local session = cache[id] - if session then - db = session.db - else - db = connect(specification) - if not db then - report("no session database specified") - else - cache[id] = { - specification = specification, - db = db, - } - end - end - else - db = connect(specification) - end - if not db then - report("no database opened") - else - local converter = specification.converter - local nofrows = 0 - local callback = nil - if converter then - local convert = converter.mysql - callback = function(nofcolumns,values,fields) - nofrows = nofrows + 1 - result[nofrows] = convert(values) - end - else - callback = function(nofcolumns,values,fields) - local column = { } - for i=1,nofcolumns do - local field - if fields then - field = fields[i] - keys[i] = field - else - field = keys[i] - end - if field then - column[field] = values[i] - end - end - nofrows = nofrows + 1 - result[nofrows] = column - end - end - for i=1,#query do - local okay = mysql_execute(db,query[i],callback) - if not okay then - if id and retry and i == 1 then - report("error: %s, retrying to connect",mysql_getmessage(db)) - mysql_close(db) - cache[id] = nil - return execute_once(specification,false) - else - report("error: %s",mysql_getmessage(db)) - end - end - end - end - if db and not id then - mysql_close(db) - end - -- bonus - local one = result[1] - if one then - setmetatable(result,{ __index = one } ) - end - -- - return result, keys - else - report("error: ","no library loaded") - end -end - -local function execute(specification) - return execute_once(specification,true) -end - --- Here we build the dataset stepwise so we don't use the data hack that --- is used in the client variant. - -local wraptemplate = [[ -local converters = utilities.sql.converters -local deserialize = utilities.sql.deserialize - -local tostring = tostring -local tonumber = tonumber -local booleanstring = string.booleanstring - -%s - -return function(cells) - -- %s (not needed) - -- %s (not needed) - return { - %s - } -end -]] - --- return function(result) --- if not result then --- return { } --- end --- local nofrows = #result --- if nofrows == 0 then --- return { } --- end --- local target = { } -- no %s needed here --- for i=1,nofrows do --- target[%s] = { --- %s --- } --- end --- return result --- end - -local celltemplate = "cells[%s]" - -methods.mysql = { - execute = execute, - usesfiles = false, - wraptemplate = wraptemplate, - celltemplate = celltemplate, -} - -package.loaded["util-sql-imp-ffi"] = methods.mysql -package.loaded["util-sql-imp-mysql"] = methods.mysql -package.loaded["util-sql-imp-library"] = methods.mysql -package.loaded[libname] = methods.mysql diff --git a/tex/context/base/mkiv/libs-imp-postgress.lmt b/tex/context/base/mkiv/libs-imp-postgress.lmt new file mode 100644 index 000000000..629079b01 --- /dev/null +++ b/tex/context/base/mkiv/libs-imp-postgress.lmt @@ -0,0 +1,200 @@ +if not modules then modules = { } end modules ['libs-imp-postgress'] = { + version = 1.001, + comment = "companion to util-sql.lua", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- Not yet untested ! + +-- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/postgress/libpq.dll + +-- we can now share the code between mysql, postgress, sqlite ... todo + +local libname = "postgress" +local libfile = "libpq" + +local postgresslib = resolvers.libraries.validoptional(libname) + +if not postgresslib then return end + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local lpegmatch = lpeg.match +local setmetatable = setmetatable + +local sql = utilities.sql or require("util-sql") +local report = logs.reporter(libname) + +local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end) +local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end) + +local postgress_open = postgresslib.open +local postgress_close = postgresslib.close +local postgress_execute = postgresslib.execute +local postgress_getmessage = postgresslib.getmessage + +local helpers = sql.helpers +local methods = sql.methods +local validspecification = helpers.validspecification +local preparetemplate = helpers.preparetemplate +local querysplitter = helpers.querysplitter -- not needed +local cache = { } + +local function connect(specification) + return postgress_open( + specification.database or "", + specification.username or "", + specification.password or "", + specification.host or "", + specification.port + ) +end + +local function execute_once(specification,retry) + if okay() then + if trace_sql then + report("executing postgress") + end + if not validspecification(specification) then + report("error in specification") + end + local query = preparetemplate(specification) + if not query then + report("error in preparation") + return + else + query = lpegmatch(querysplitter,query) -- not needed + end + local base = specification.database -- or specification.presets and specification.presets.database + if not base then + report("no database specified") + return + end + local result = { } + local keys = { } + local id = specification.id + local db = nil + if id then + local session = cache[id] + if session then + db = session.db + else + db = connect(specification) + if not db then + report("no session database specified") + else + cache[id] = { + specification = specification, + db = db, + } + end + end + else + db = connect(specification) + end + if not db then + report("no database opened") + else + local converter = specification.converter + local nofrows = 0 + local callback = nil + if converter then + local convert = converter.postgress + callback = function(nofcolumns,values,fields) + nofrows = nofrows + 1 + result[nofrows] = convert(values) + end + else + callback = function(nofcolumns,values,fields) + local column = { } + for i=1,nofcolumns do + local field + if fields then + field = fields[i] + keys[i] = field + else + field = keys[i] + end + if field then + column[field] = values[i] + end + end + nofrows = nofrows + 1 + result[nofrows] = column + end + end + for i=1,#query do + local okay = postgress_execute(db,query[i],callback) + if not okay then + if id and retry and i == 1 then + report("error: %s, retrying to connect",postgress_getmessage(db)) + postgress_close(db) + cache[id] = nil + return execute_once(specification,false) + else + report("error: %s",postgress_getmessage(db)) + end + end + end + end + if db and not id then + postgress_close(db) + end + -- bonus + local one = result[1] + if one then + setmetatable(result,{ __index = one } ) + end + -- + return result, keys + else + report("error: ","no library loaded") + end +end + +local function execute(specification) + return execute_once(specification,true) +end + +-- Here we build the dataset stepwise so we don't use the data hack that +-- is used in the client variant. + +local wraptemplate = [[ +local converters = utilities.sql.converters +local deserialize = utilities.sql.deserialize + +local tostring = tostring +local tonumber = tonumber +local booleanstring = string.booleanstring + +%s + +return function(cells) + -- %s (not needed) + -- %s (not needed) + return { + %s + } +end +]] + +local celltemplate = "cells[%s]" + +methods.postgress = { + execute = execute, + usesfiles = false, + wraptemplate = wraptemplate, + celltemplate = celltemplate, +} + +package.loaded["util-sql-imp-postgress"] = methods.postgress +package.loaded[libname] = methods.postgress diff --git a/tex/context/base/mkiv/libs-imp-postgress.lua b/tex/context/base/mkiv/libs-imp-postgress.lua deleted file mode 100644 index 629079b01..000000000 --- a/tex/context/base/mkiv/libs-imp-postgress.lua +++ /dev/null @@ -1,200 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-postgress'] = { - version = 1.001, - comment = "companion to util-sql.lua", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- Not yet untested ! - --- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/postgress/libpq.dll - --- we can now share the code between mysql, postgress, sqlite ... todo - -local libname = "postgress" -local libfile = "libpq" - -local postgresslib = resolvers.libraries.validoptional(libname) - -if not postgresslib then return end - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local lpegmatch = lpeg.match -local setmetatable = setmetatable - -local sql = utilities.sql or require("util-sql") -local report = logs.reporter(libname) - -local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end) -local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end) - -local postgress_open = postgresslib.open -local postgress_close = postgresslib.close -local postgress_execute = postgresslib.execute -local postgress_getmessage = postgresslib.getmessage - -local helpers = sql.helpers -local methods = sql.methods -local validspecification = helpers.validspecification -local preparetemplate = helpers.preparetemplate -local querysplitter = helpers.querysplitter -- not needed -local cache = { } - -local function connect(specification) - return postgress_open( - specification.database or "", - specification.username or "", - specification.password or "", - specification.host or "", - specification.port - ) -end - -local function execute_once(specification,retry) - if okay() then - if trace_sql then - report("executing postgress") - end - if not validspecification(specification) then - report("error in specification") - end - local query = preparetemplate(specification) - if not query then - report("error in preparation") - return - else - query = lpegmatch(querysplitter,query) -- not needed - end - local base = specification.database -- or specification.presets and specification.presets.database - if not base then - report("no database specified") - return - end - local result = { } - local keys = { } - local id = specification.id - local db = nil - if id then - local session = cache[id] - if session then - db = session.db - else - db = connect(specification) - if not db then - report("no session database specified") - else - cache[id] = { - specification = specification, - db = db, - } - end - end - else - db = connect(specification) - end - if not db then - report("no database opened") - else - local converter = specification.converter - local nofrows = 0 - local callback = nil - if converter then - local convert = converter.postgress - callback = function(nofcolumns,values,fields) - nofrows = nofrows + 1 - result[nofrows] = convert(values) - end - else - callback = function(nofcolumns,values,fields) - local column = { } - for i=1,nofcolumns do - local field - if fields then - field = fields[i] - keys[i] = field - else - field = keys[i] - end - if field then - column[field] = values[i] - end - end - nofrows = nofrows + 1 - result[nofrows] = column - end - end - for i=1,#query do - local okay = postgress_execute(db,query[i],callback) - if not okay then - if id and retry and i == 1 then - report("error: %s, retrying to connect",postgress_getmessage(db)) - postgress_close(db) - cache[id] = nil - return execute_once(specification,false) - else - report("error: %s",postgress_getmessage(db)) - end - end - end - end - if db and not id then - postgress_close(db) - end - -- bonus - local one = result[1] - if one then - setmetatable(result,{ __index = one } ) - end - -- - return result, keys - else - report("error: ","no library loaded") - end -end - -local function execute(specification) - return execute_once(specification,true) -end - --- Here we build the dataset stepwise so we don't use the data hack that --- is used in the client variant. - -local wraptemplate = [[ -local converters = utilities.sql.converters -local deserialize = utilities.sql.deserialize - -local tostring = tostring -local tonumber = tonumber -local booleanstring = string.booleanstring - -%s - -return function(cells) - -- %s (not needed) - -- %s (not needed) - return { - %s - } -end -]] - -local celltemplate = "cells[%s]" - -methods.postgress = { - execute = execute, - usesfiles = false, - wraptemplate = wraptemplate, - celltemplate = celltemplate, -} - -package.loaded["util-sql-imp-postgress"] = methods.postgress -package.loaded[libname] = methods.postgress diff --git a/tex/context/base/mkiv/libs-imp-sqlite.lmt b/tex/context/base/mkiv/libs-imp-sqlite.lmt new file mode 100644 index 000000000..5d38986f3 --- /dev/null +++ b/tex/context/base/mkiv/libs-imp-sqlite.lmt @@ -0,0 +1,187 @@ +if not modules then modules = { } end modules ['libs-imp-sqlite'] = { + version = 1.001, + comment = "companion to util-sql.lua", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/sqlite/sqlite3.dll + +local libname = "sqlite" +local libfile = "sqlite3" + +local sqlitelib = resolvers.libraries.validoptional(libname) + +if not sqlitelib then return end + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local next, tonumber = next, tonumber +local setmetatable = setmetatable +local formatters = string.formatters + +local sql = utilities.sql or require("util-sql") +local report = logs.reporter(libname) + +local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end) +local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end) + +local sqlite_open = sqlitelib.open +local sqlite_close = sqlitelib.close +local sqlite_execute = sqlitelib.execute +local sqlite_getmessage = sqlitelib.getmessage + +local helpers = sql.helpers +local methods = sql.methods +local validspecification = helpers.validspecification +local preparetemplate = helpers.preparetemplate +local cache = { } + +-- synchronous journal_mode locking_mode 1000 logger inserts +-- +-- normal normal normal 6.8 +-- off off normal 0.1 +-- normal off normal 2.1 +-- normal persist normal 5.8 +-- normal truncate normal 4.2 +-- normal truncate exclusive 4.1 + +local f_preamble = formatters[ [[ +ATTACH `%s` AS `%s` ; +PRAGMA `%s`.synchronous = normal ; +]] ] + +local function execute(specification) + if okay() then + if trace_sql then + report("executing sqlite") + end + if not validspecification(specification) then + report("error in specification") + end + local query = preparetemplate(specification) + if not query then + report("error in preparation") + return + end + local base = specification.database -- or specification.presets and specification.presets.database + if not base then + report("no database specified") + return + end + local filename = file.addsuffix(base,"db") + local result = { } + local keys = { } + local id = specification.id + local db = nil + local preamble = nil + if id then + local session = cache[id] + if session then + db = session.db + else + db = sqlite_open(filename) + preamble = f_preamble(filename,base,base) + if not db then + report("no session database specified") + else + cache[id] = { + name = filename, + db = db, + } + end + end + else + db = open_db(filename) + preamble = f_preamble(filename,base,base) + end + if not db then + report("no database opened") + else + local converter = specification.converter + local nofrows = 0 + local callback = nil + if preamble then + query = preamble .. query -- only needed in open + end + if converter then + local convert = converter.sqlite + callback = function(nofcolumns,values,fields) + nofrows = nofrows + 1 + result[nofrows] = convert(values) + end + else + callback = function(nofcolumns,values,fields) + local column = { } + for i=1,nofcolumns do + local field + if fields then + field = fields[i] + keys[i] = field + else + field = keys[i] + end + if field then + column[field] = values[i] + end + end + nofrows = nofrows + 1 + result[nofrows] = column + end + end + local okay = sqlite_execute(db,query,callback) + if not okay then + report("error: %s",sqlite_getmessage(db)) + -- elseif converter then + -- result = converter.sqlite(result) + end + end + if db and not id then + sqlite_close(db) + end + return result, keys + else + report("error: ","no library loaded") + end +end + +local wraptemplate = [[ +local converters = utilities.sql.converters +local deserialize = utilities.sql.deserialize + +local tostring = tostring +local tonumber = tonumber +local booleanstring = string.booleanstring + +%s + +return function(cells) + -- %s (not needed) + -- %s (not needed) + return { + %s + } +end +]] + +local celltemplate = "cells[%s]" + +methods.sqlite = { + execute = execute, + usesfiles = false, + wraptemplate = wraptemplate, + celltemplate = celltemplate, +} + +package.loaded["util-sql-imp-sqlite"] = methods.sqlite +package.loaded[libname] = methods.sqlite + +return methods.sqlite diff --git a/tex/context/base/mkiv/libs-imp-sqlite.lua b/tex/context/base/mkiv/libs-imp-sqlite.lua deleted file mode 100644 index 5d38986f3..000000000 --- a/tex/context/base/mkiv/libs-imp-sqlite.lua +++ /dev/null @@ -1,187 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-sqlite'] = { - version = 1.001, - comment = "companion to util-sql.lua", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/sqlite/sqlite3.dll - -local libname = "sqlite" -local libfile = "sqlite3" - -local sqlitelib = resolvers.libraries.validoptional(libname) - -if not sqlitelib then return end - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local next, tonumber = next, tonumber -local setmetatable = setmetatable -local formatters = string.formatters - -local sql = utilities.sql or require("util-sql") -local report = logs.reporter(libname) - -local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end) -local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end) - -local sqlite_open = sqlitelib.open -local sqlite_close = sqlitelib.close -local sqlite_execute = sqlitelib.execute -local sqlite_getmessage = sqlitelib.getmessage - -local helpers = sql.helpers -local methods = sql.methods -local validspecification = helpers.validspecification -local preparetemplate = helpers.preparetemplate -local cache = { } - --- synchronous journal_mode locking_mode 1000 logger inserts --- --- normal normal normal 6.8 --- off off normal 0.1 --- normal off normal 2.1 --- normal persist normal 5.8 --- normal truncate normal 4.2 --- normal truncate exclusive 4.1 - -local f_preamble = formatters[ [[ -ATTACH `%s` AS `%s` ; -PRAGMA `%s`.synchronous = normal ; -]] ] - -local function execute(specification) - if okay() then - if trace_sql then - report("executing sqlite") - end - if not validspecification(specification) then - report("error in specification") - end - local query = preparetemplate(specification) - if not query then - report("error in preparation") - return - end - local base = specification.database -- or specification.presets and specification.presets.database - if not base then - report("no database specified") - return - end - local filename = file.addsuffix(base,"db") - local result = { } - local keys = { } - local id = specification.id - local db = nil - local preamble = nil - if id then - local session = cache[id] - if session then - db = session.db - else - db = sqlite_open(filename) - preamble = f_preamble(filename,base,base) - if not db then - report("no session database specified") - else - cache[id] = { - name = filename, - db = db, - } - end - end - else - db = open_db(filename) - preamble = f_preamble(filename,base,base) - end - if not db then - report("no database opened") - else - local converter = specification.converter - local nofrows = 0 - local callback = nil - if preamble then - query = preamble .. query -- only needed in open - end - if converter then - local convert = converter.sqlite - callback = function(nofcolumns,values,fields) - nofrows = nofrows + 1 - result[nofrows] = convert(values) - end - else - callback = function(nofcolumns,values,fields) - local column = { } - for i=1,nofcolumns do - local field - if fields then - field = fields[i] - keys[i] = field - else - field = keys[i] - end - if field then - column[field] = values[i] - end - end - nofrows = nofrows + 1 - result[nofrows] = column - end - end - local okay = sqlite_execute(db,query,callback) - if not okay then - report("error: %s",sqlite_getmessage(db)) - -- elseif converter then - -- result = converter.sqlite(result) - end - end - if db and not id then - sqlite_close(db) - end - return result, keys - else - report("error: ","no library loaded") - end -end - -local wraptemplate = [[ -local converters = utilities.sql.converters -local deserialize = utilities.sql.deserialize - -local tostring = tostring -local tonumber = tonumber -local booleanstring = string.booleanstring - -%s - -return function(cells) - -- %s (not needed) - -- %s (not needed) - return { - %s - } -end -]] - -local celltemplate = "cells[%s]" - -methods.sqlite = { - execute = execute, - usesfiles = false, - wraptemplate = wraptemplate, - celltemplate = celltemplate, -} - -package.loaded["util-sql-imp-sqlite"] = methods.sqlite -package.loaded[libname] = methods.sqlite - -return methods.sqlite diff --git a/tex/context/base/mkiv/libs-imp-zint.lmt b/tex/context/base/mkiv/libs-imp-zint.lmt new file mode 100644 index 000000000..2c346ae7d --- /dev/null +++ b/tex/context/base/mkiv/libs-imp-zint.lmt @@ -0,0 +1,161 @@ +if not modules then modules = { } end modules ['libs-imp-ghostscript'] = { + version = 1.001, + comment = "companion to luat-lib.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", +} + +local libname = "zint" +local libfile = "libzint" -- what on unix? +-- local libfile = "/usr/local/lib/libzint.so" + +local zintlib = resolvers.libraries.validoptional(libname) + +if not zintlib then return end + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local zint = utilities.zint or { } +utilities.zint = zint + +local zintlib_execute = zintlib.execute + +local next, type, unpack = next, type, unpack +local lower, gsub = string.lower, string.gsub + +local mapping = { + ["code 11"] = 1, ["pharma one-track"] = 51, ["aztec code"] = 92, + ["standard 2of5"] = 2, ["pzn"] = 52, ["daft code"] = 93, + ["interleaved 2of5"] = 3, ["pharma two-track"] = 53, ["micro qr code"] = 97, + ["iata 2of5"] = 4, ["pdf417"] = 55, ["hibc code 128"] = 98, + ["data logic"] = 6, ["pdf417 trunc"] = 56, ["hibc code 39"] = 99, + ["industrial 2of5"] = 7, ["maxicode"] = 57, ["hibc data matrix"] = 102, + ["code 39"] = 8, ["qr code"] = 58, ["hibc qr code"] = 104, + ["extended code 39"] = 9, ["code 128-b"] = 60, ["hibc pdf417"] = 106, + ["ean"] = 13, ["ap standard customer"] = 63, ["hibc micropdf417"] = 108, + ["ean + check"] = 14, ["ap reply paid"] = 66, ["hibc codablock-f"] = 110, + ["gs1-128"] = 16, ["ap routing"] = 67, ["hibc aztec code"] = 112, + ["codabar"] = 18, ["ap redirection"] = 68, ["dotcode"] = 115, + ["code 128"] = 20, ["isbn"] = 69, ["han xin code"] = 116, + ["leitcode"] = 21, ["rm4scc"] = 70, ["rm mailmark"] = 121, + ["identcode"] = 22, ["data matrix"] = 71, ["aztec runes"] = 128, + ["code 16k"] = 23, ["ean-14"] = 72, ["code 32"] = 129, + ["code 49"] = 24, ["vin (north america)"] = 73, ["comp ean"] = 130, + ["code 93"] = 25, ["codablock-f"] = 74, ["comp gs1-128"] = 131, + ["flattermarken"] = 28, ["nve-18"] = 75, ["comp databar omni"] = 132, + ["gs1 databar omni"] = 29, ["japanese post"] = 76, ["comp databar ltd"] = 133, + ["gs1 databar ltd"] = 30, ["korea post"] = 77, ["comp databar expom"] = 134, + ["gs1 databar expom"] = 31, ["gs1 databar stack"] = 79, ["comp upc-a"] = 135, + ["telepen alpha"] = 32, ["gs1 databar stack omni"] = 80, ["comp upc-e"] = 136, + ["upc-a"] = 34, ["gs1 databar eso"] = 81, ["comp databar stack"] = 137, + ["upc-a + check"] = 35, ["planet"] = 82, ["comp databar stack omni"] = 138, + ["upc-e"] = 37, ["micropdf"] = 84, ["comp databar eso"] = 139, + ["upc-e + check"] = 38, ["usps onecode"] = 85, ["channel code"] = 140, + ["postnet"] = 40, ["uk plessey"] = 86, ["code one"] = 141, + ["msi plessey"] = 47, ["telepen numeric"] = 87, ["grid matrix"] = 142, + ["fim"] = 49, ["itf-14"] = 89, ["upnqr"] = 143, + ["logmars"] = 50, ["kix code"] = 90, ["rmqr"] = 145, +} + +table.setmetatableindex(mapping,function(t,k) + local s = gsub(lower(k),"[^a-z0-9]","") + local v = rawget(t,s) or false + t[k] = v + return v +end) + +local report = logs.reporter("zint") +local context = context +local shown = false + +----- f_rectangle = string.formatters["%sofill unitsquare xysized (%N,%N) shifted (%N,%N);"] + +local function execute(specification) + if okay() then + local code = specification.code + local text = specification.text + if code then + local id = mapping[code] + if id then + specification.code = id + local result = zintlib_execute(specification) + if result then + -- not that fast but if needed we can speed it up + context.startMPcode() + local rectangles = result.rectangles + local hexagons = result.hexagons + local circles = result.circles + local strings = result.strings + if rectangles then + local n = #rectangles + for i=1,n do + local r = rectangles[i] + context("%sofill unitsquare xysized (%N,%N) shifted (%N,%N);", + i == n and "d" or "n",r[3],r[4],r[1],r[2]) + -- rectangles[i] = f_rectangle(i == n and "d" or "n",r[3],r[4],r[1],r[2]) + end + -- context("% t",rectangles) + end + if hexagons then + local n = #hexagons + for i=1,#hexagons do + context("%sofill (%N,%N)--(%N,%N)--(%N,%N)--(%N,%N)--(%N,%N)--(%N,%N)--cycle;", + i == n and "d" or "n",unpack(hexagons[i])) + end + end + if circles then + local n = #circles + for i=1,#circles do + local c = circles[i] + context("%sofill unitcircle scaled %N shifted (%N,%N);", + i == n and "d" or "n",c[3],c[1],c[2]) + end + end + if strings then + -- We set the font at the encapsulating level. + for i=1,#strings do + local s = strings[i] + context('draw textext("%s") scaled (%N/10) shifted (%N,%N);', + s[4],s[3],s[1],s[2]) + end + end + context.stopMPcode() + end + else + report("unknown barcode alternative %a",code) + if not shown then + report("") + report("valid barcode alternatives:") + report("") + local list = table.sortedkeys(mapping) + for i=1,#list do + report(" %s", list[i]) + end + report("") + shown = true + end + end + end + end +end + +optional.loaded.zint = { execute = execute } + +interfaces.implement { + name = "zint", + actions = execute, + arguments = { + { + { "code" }, + { "text" }, + } + } +} diff --git a/tex/context/base/mkiv/libs-imp-zint.lua b/tex/context/base/mkiv/libs-imp-zint.lua deleted file mode 100644 index 2c346ae7d..000000000 --- a/tex/context/base/mkiv/libs-imp-zint.lua +++ /dev/null @@ -1,161 +0,0 @@ -if not modules then modules = { } end modules ['libs-imp-ghostscript'] = { - version = 1.001, - comment = "companion to luat-lib.mkxl", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files", -} - -local libname = "zint" -local libfile = "libzint" -- what on unix? --- local libfile = "/usr/local/lib/libzint.so" - -local zintlib = resolvers.libraries.validoptional(libname) - -if not zintlib then return end - -local function okay() - if resolvers.libraries.optionalloaded(libname,libfile) then - okay = function() return true end - else - okay = function() return false end - end - return okay() -end - -local zint = utilities.zint or { } -utilities.zint = zint - -local zintlib_execute = zintlib.execute - -local next, type, unpack = next, type, unpack -local lower, gsub = string.lower, string.gsub - -local mapping = { - ["code 11"] = 1, ["pharma one-track"] = 51, ["aztec code"] = 92, - ["standard 2of5"] = 2, ["pzn"] = 52, ["daft code"] = 93, - ["interleaved 2of5"] = 3, ["pharma two-track"] = 53, ["micro qr code"] = 97, - ["iata 2of5"] = 4, ["pdf417"] = 55, ["hibc code 128"] = 98, - ["data logic"] = 6, ["pdf417 trunc"] = 56, ["hibc code 39"] = 99, - ["industrial 2of5"] = 7, ["maxicode"] = 57, ["hibc data matrix"] = 102, - ["code 39"] = 8, ["qr code"] = 58, ["hibc qr code"] = 104, - ["extended code 39"] = 9, ["code 128-b"] = 60, ["hibc pdf417"] = 106, - ["ean"] = 13, ["ap standard customer"] = 63, ["hibc micropdf417"] = 108, - ["ean + check"] = 14, ["ap reply paid"] = 66, ["hibc codablock-f"] = 110, - ["gs1-128"] = 16, ["ap routing"] = 67, ["hibc aztec code"] = 112, - ["codabar"] = 18, ["ap redirection"] = 68, ["dotcode"] = 115, - ["code 128"] = 20, ["isbn"] = 69, ["han xin code"] = 116, - ["leitcode"] = 21, ["rm4scc"] = 70, ["rm mailmark"] = 121, - ["identcode"] = 22, ["data matrix"] = 71, ["aztec runes"] = 128, - ["code 16k"] = 23, ["ean-14"] = 72, ["code 32"] = 129, - ["code 49"] = 24, ["vin (north america)"] = 73, ["comp ean"] = 130, - ["code 93"] = 25, ["codablock-f"] = 74, ["comp gs1-128"] = 131, - ["flattermarken"] = 28, ["nve-18"] = 75, ["comp databar omni"] = 132, - ["gs1 databar omni"] = 29, ["japanese post"] = 76, ["comp databar ltd"] = 133, - ["gs1 databar ltd"] = 30, ["korea post"] = 77, ["comp databar expom"] = 134, - ["gs1 databar expom"] = 31, ["gs1 databar stack"] = 79, ["comp upc-a"] = 135, - ["telepen alpha"] = 32, ["gs1 databar stack omni"] = 80, ["comp upc-e"] = 136, - ["upc-a"] = 34, ["gs1 databar eso"] = 81, ["comp databar stack"] = 137, - ["upc-a + check"] = 35, ["planet"] = 82, ["comp databar stack omni"] = 138, - ["upc-e"] = 37, ["micropdf"] = 84, ["comp databar eso"] = 139, - ["upc-e + check"] = 38, ["usps onecode"] = 85, ["channel code"] = 140, - ["postnet"] = 40, ["uk plessey"] = 86, ["code one"] = 141, - ["msi plessey"] = 47, ["telepen numeric"] = 87, ["grid matrix"] = 142, - ["fim"] = 49, ["itf-14"] = 89, ["upnqr"] = 143, - ["logmars"] = 50, ["kix code"] = 90, ["rmqr"] = 145, -} - -table.setmetatableindex(mapping,function(t,k) - local s = gsub(lower(k),"[^a-z0-9]","") - local v = rawget(t,s) or false - t[k] = v - return v -end) - -local report = logs.reporter("zint") -local context = context -local shown = false - ------ f_rectangle = string.formatters["%sofill unitsquare xysized (%N,%N) shifted (%N,%N);"] - -local function execute(specification) - if okay() then - local code = specification.code - local text = specification.text - if code then - local id = mapping[code] - if id then - specification.code = id - local result = zintlib_execute(specification) - if result then - -- not that fast but if needed we can speed it up - context.startMPcode() - local rectangles = result.rectangles - local hexagons = result.hexagons - local circles = result.circles - local strings = result.strings - if rectangles then - local n = #rectangles - for i=1,n do - local r = rectangles[i] - context("%sofill unitsquare xysized (%N,%N) shifted (%N,%N);", - i == n and "d" or "n",r[3],r[4],r[1],r[2]) - -- rectangles[i] = f_rectangle(i == n and "d" or "n",r[3],r[4],r[1],r[2]) - end - -- context("% t",rectangles) - end - if hexagons then - local n = #hexagons - for i=1,#hexagons do - context("%sofill (%N,%N)--(%N,%N)--(%N,%N)--(%N,%N)--(%N,%N)--(%N,%N)--cycle;", - i == n and "d" or "n",unpack(hexagons[i])) - end - end - if circles then - local n = #circles - for i=1,#circles do - local c = circles[i] - context("%sofill unitcircle scaled %N shifted (%N,%N);", - i == n and "d" or "n",c[3],c[1],c[2]) - end - end - if strings then - -- We set the font at the encapsulating level. - for i=1,#strings do - local s = strings[i] - context('draw textext("%s") scaled (%N/10) shifted (%N,%N);', - s[4],s[3],s[1],s[2]) - end - end - context.stopMPcode() - end - else - report("unknown barcode alternative %a",code) - if not shown then - report("") - report("valid barcode alternatives:") - report("") - local list = table.sortedkeys(mapping) - for i=1,#list do - report(" %s", list[i]) - end - report("") - shown = true - end - end - end - end -end - -optional.loaded.zint = { execute = execute } - -interfaces.implement { - name = "zint", - actions = execute, - arguments = { - { - { "code" }, - { "text" }, - } - } -} diff --git a/tex/context/base/mkiv/libs-imp-zint.mkxl b/tex/context/base/mkiv/libs-imp-zint.mkxl index 72ce8157e..fbea52888 100644 --- a/tex/context/base/mkiv/libs-imp-zint.mkxl +++ b/tex/context/base/mkiv/libs-imp-zint.mkxl @@ -22,7 +22,7 @@ %D There is a bit more code than needed as we want to be able to %D feed names. -\registerctxluafile{libs-imp-zint}{} +\registerctxluafile{libs-imp-zint}{autosuffix} \unprotect diff --git a/tex/context/base/mkiv/libs-ini.lua b/tex/context/base/mkiv/libs-ini.lua index 5fc8ded98..7f1645b44 100644 --- a/tex/context/base/mkiv/libs-ini.lua +++ b/tex/context/base/mkiv/libs-ini.lua @@ -13,10 +13,10 @@ if not modules then modules = { } end modules ['libs-ini'] = { -- is doing. local type, unpack = type, unpack +local find = string.find -- here we implement the resolver -local type = type local nameonly = file.nameonly local joinfile = file.join @@ -196,3 +196,19 @@ end -- } -- end -- } + +local dofile = dofile +local savedrequire = require + +function require(name,version) + if find(name,"%.lua$") or find(name,"%.lmt$") then + local m = dofile(findfile(name)) + if m then + package.loaded[name] = m + return m + end + else + return savedrequire(name) + end +end + diff --git a/tex/context/base/mkiv/libs-ini.mkxl b/tex/context/base/mkiv/libs-ini.mkxl index 18163beed..e04c7c193 100644 --- a/tex/context/base/mkiv/libs-ini.mkxl +++ b/tex/context/base/mkiv/libs-ini.mkxl @@ -11,17 +11,18 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\registerctxluafile{libs-ini}{} +\registerctxluafile{libs-ini}{} % shared with mkiv -\registerctxluafile{libs-imp-curl}{} -\registerctxluafile{libs-imp-ghostscript}{} -\registerctxluafile{libs-imp-graphicsmagick}{} +\registerctxluafile{libs-imp-curl}{autosuffix} +\registerctxluafile{libs-imp-ghostscript}{autosuffix} +\registerctxluafile{libs-imp-graphicsmagick}{autosuffix} % These are loaded on demand: -% \registerctxluafile{libs-imp-mysql}{} -% \registerctxluafile{libs-imp-sqlite}{} -% \registerctxluafile{libs-imp-postgress}{} +% \registerctxluafile{libs-imp-mysql}{autosuffix} +% \registerctxluafile{libs-imp-sqlite}{autosuffix} +% \registerctxluafile{libs-imp-postgress}{autosuffix} +% \registerctxluafile{libs-imp-kpse}{autosuffix} \unprotect diff --git a/tex/context/base/mkiv/lpdf-ano.lua b/tex/context/base/mkiv/lpdf-ano.lua index c04ada151..a120ff2f4 100644 --- a/tex/context/base/mkiv/lpdf-ano.lua +++ b/tex/context/base/mkiv/lpdf-ano.lua @@ -712,7 +712,8 @@ function codeinjections.prerollreference(actions) -- share can become option local bs, bc = pdfborder() main = pdfdictionary { Subtype = pdf_link, - Border = bs, + -- Border = bs, + Border = pdfshareobjectreference(bs), C = bc, H = (not actions.highlight and pdf_n) or nil, A = pdfshareobjectreference(main), diff --git a/tex/context/base/mkiv/lpdf-col.lua b/tex/context/base/mkiv/lpdf-col.lua index c586300e5..d3b612593 100644 --- a/tex/context/base/mkiv/lpdf-col.lua +++ b/tex/context/base/mkiv/lpdf-col.lua @@ -818,14 +818,20 @@ do end end + -- A problem is that we need to transfer back and this is kind of + -- messy so we force text mode .. i'll do a better job on that but + -- will experiment first (both engines). Virtual fonts will change + -- anyway. + backends.pdf.tables.vfspecials = allocate { -- todo: distinguish between glyph and rule color startcolor = startcolor, -- stopcolor = { "pdf", "page", "0 g 0 G Q" }, - stopcolor = { "pdf", "page", "Q" }, + stopcolor = { "pdf", "text", "Q" }, startslant = startslant, - stopslant = { "pdf", "origin", "Q" }, + -- stopslant = { "pdf", "origin", "Q" }, + stopslant = { "pdf", "text", "Q" }, } diff --git a/tex/context/base/mkiv/lpdf-emb.lmt b/tex/context/base/mkiv/lpdf-emb.lmt new file mode 100644 index 000000000..0f0388af0 --- /dev/null +++ b/tex/context/base/mkiv/lpdf-emb.lmt @@ -0,0 +1,2225 @@ +if not modules then modules = { } end modules ['lpdf-ini'] = { + version = 1.001, + optimize = true, + 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" +} + +-- vkgoeswild: Pink Floyd - Shine on You Crazy Diamond - piano cover (around that +-- time I redid the code, a reminder so to say) + +-- At some point I wanted to have access to the shapes so that we could use them in +-- metapost. So, after looking at the cff and ttf specifications, I decided to write +-- parsers. At somepoint we needed a cff parser anyway in order to calculate the +-- dimensions. Then variable fonts came around and a option was added to recreate +-- streams of operators and a logical next step was to do all inclusion that way. It +-- was only then that I found out that some of the juggling also happens in the the +-- backend, but spread over places, so I could have saved myself some time +-- deciphering the specifications. Anyway, here we go. +-- +-- Color fonts are a bit messy. Catching issues with older fonts will break new ones +-- so I don't think that it's wise to build in too many catches (like for fonts with +-- zero boundingboxes, weird dimensions, transformations that in a next version are +-- fixed, etc.). Better is then to wait till something gets fixed. If a spec doesn't +-- tell me how to deal with it ... I'll happily wait till it does. After all we're +-- not in a hurry as these fonts are mostly meant for the web or special purposes +-- with manual tweaking in desk top publishing applications. Keep in mind that Emoji +-- can have funny dimensions (e.g. to be consistent within a font, so no tight ones). + +-- When we have moved to lmtx I will document a bit more. Till then it's experimental +-- and subjected to change. + +local next, type, unpack, rawget = next, type, unpack, rawget +local char, byte, gsub, sub, match, rep, gmatch = string.char, string.byte, string.gsub, string.sub, string.match, string.rep, string.gmatch +local formatters = string.formatters +local format = string.format +local concat, sortedhash, sort = table.concat, table.sortedhash, table.sort +local utfchar = utf.char +local random, round, max, abs, ceiling = math.random, math.round, math.max, math.abs, math.ceiling +local extract, lshift, rshift, band, bor = bit32.extract, bit32.lshift, bit32.rshift, bit32.band, bit32.bor +local idiv = number.idiv +local setmetatableindex = table.setmetatableindex + +local pdfnull = lpdf.null +local pdfdictionary = lpdf.dictionary +local pdfarray = lpdf.array +local pdfconstant = lpdf.constant +local pdfstring = lpdf.string +local pdfreference = lpdf.reference +local pdfreserveobject = lpdf.reserveobject +local pdfflushobject = lpdf.flushobject +local pdfflushstreamobject = lpdf.flushstreamobject + +local report_fonts = logs.reporter("backend","fonts") + +local trace_fonts = false +local trace_details = false + +local dimenfactors = number.dimenfactors +local bpfactor = dimenfactors.bp +local ptfactor = dimenfactors.pt + +trackers.register("backend.pdf.fonts",function(v) trace_fonts = v end) + +local readers = fonts.handlers.otf.readers +local getinfo = readers.getinfo + +local setposition = utilities.files.setposition +local readstring = utilities.files.readstring +local openfile = utilities.files.open +local closefile = utilities.files.close + + +-- needs checking: signed vs unsigned + +local tocardinal1 = char + +local function tocardinal2(n) + return char(extract(n,8,8),extract(n,0,8)) +end + +local function tocardinal3(n) + return char(extract(n,16,8),extract(n,8,8),extract(n,0,8)) +end + +local function tocardinal4(n) + return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) +end + +local function tointeger2(n) + return char(extract(n,8,8),extract(n,0,8)) +end + +local function tointeger3(n) + return char(extract(n,16,8),extract(n,8,8),extract(n,0,8)) +end + +local function tointeger4(n) + return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) +end + +local function tocardinal8(n) + local l = idiv(n,0x100000000) + local r = n % 0x100000000 + return char(extract(l,24,8),extract(l,16,8),extract(l,8,8),extract(l,0,8), + extract(r,24,8),extract(r,16,8),extract(r,8,8),extract(r,0,8)) +end + +-- A couple of shared helpers. + +local tounicodedictionary, widtharray, collectindices, subsetname, includecidset, forcecidset, tocidsetdictionary + +do + + -- Because we supply tounicodes ourselves we only use bfchar mappings (as in the + -- backend). In fact, we can now no longer pass the tounicodes to the frontend but + -- pick them up from the descriptions. + + local f_mapping_2 = formatters["<%02X> <%s>"] + local f_mapping_4 = formatters["<%04X> <%s>"] + + local tounicode = fonts.mappings.tounicode + +local tounicode_template = [[ +%%!PS-Adobe-3.0 Resource-CMap +%%%%DocumentNeededResources: ProcSet (CIDInit) +%%%%IncludeResource: ProcSet (CIDInit) +%%%%BeginResource: CMap (TeX-%s-0) +%%%%Title: (TeX-%s-0 TeX %s 0)| +%%%%Version: 1.000 +%%%%EndComments +/CIDInit /ProcSet findresource begin + 12 dict begin + begincmap + /CIDSystemInfo + << /Registry (TeX) /Ordering (%s) /Supplement 0 >> + def + /CMapName + /TeX-Identity-%s + def + /CMapType + 2 + def + 1 begincodespacerange + <%s> <%s> + endcodespacerange + %i beginbfchar +%s + endbfchar + endcmap + CMapName currentdict /CMap defineresource pop + end +end +%%%%EndResource +%%%%EOF]] + + tounicodedictionary = function(details,indices,maxindex,name,wide) + local mapping = { } + local length = 0 + if maxindex > 0 then + local f_mapping = wide and f_mapping_4 or f_mapping_2 + for index=1,maxindex do + local data = indices[index] + if data then + length = length + 1 + local unicode = data.unicode + if unicode then + unicode = tounicode(unicode) + else + unicode = "FFFD" + end + mapping[length] = f_mapping(index,unicode) + end + end + end + local name = gsub(name,"%+","-") -- like luatex does + local first = wide and "0000" or "00" + local last = wide and "FFFF" or "FF" + local blob = format(tounicode_template,name,name,name,name,name,first,last,length,concat(mapping,"\n")) + return blob + end + + widtharray = function(details,indices,maxindex,units) + local widths = pdfarray() + local length = 0 + local factor = 10000 / units + if maxindex > 0 then + local lastindex = -1 + local sublist = nil + for index=1,maxindex do + local data = indices[index] + if data then + local width = data.width -- hm, is inaccurate for cff, so take from elsewhere + if width then + -- width = round(width * 10000 / units) / 10 + width = round(width * factor) / 10 + else + width = 0 + end + if index == lastindex + 1 then + sublist[#sublist+1] = width + else + if sublist then + length = length + 1 + widths[length] = sublist + end + sublist = pdfarray { width } + length = length + 1 + widths[length] = index + end + lastindex = index + end + end + length = length + 1 + widths[length] = sublist + end + return widths + end + + collectindices = function(descriptions,indices) + local minindex = 0xFFFF + local maxindex = 0 + local reverse = { } + -- todo: already at definition time trigger copying streams + -- and add extra indices ... first i need a good example of + -- a clash + -- for unicode, data in next, descriptions do + -- local i = data.index or unicode + -- if reverse[i] then + -- print("CLASH") + -- else + -- reverse[i] = data + -- end + -- end + for unicode, data in next, descriptions do + reverse[data.index or unicode] = data + end + for index in next, indices do + if index > maxindex then + maxindex = index + end + if index < minindex then + minindex = index + end + indices[index] = reverse[index] + end + if minindex > maxindex then + minindex = maxindex + end + return indices, minindex, maxindex + end + + includecidset = false + forcecidset = false -- for private testing only + + directives.register("backend.pdf.forcecidset",function(v) + forcecidset = v + end) + + tocidsetdictionary = function(indices,min,max) + if includecidset or forcecidset then + local b = { } + local m = idiv(max+7,8) + for i=0,max do + b[i] = 0 + end + b[0] = bor(b[0],lshift(1,7)) -- force notdef into the file + for i=min,max do + if indices[i] then + local bi = idiv(i,8) + local ni = i % 8 + b[bi] = bor(b[bi],lshift(1,7-ni)) + end + end + b = char(unpack(b,0,#b)) + return pdfreference(pdfflushstreamobject(b)) + end + end + + -- Actually we can use the same as we only embed once. + + -- subsetname = function(name) + -- return "CONTEXT" .. name + -- end + + local prefixes = { } -- todo: set fixed one + + subsetname = function(name) + local prefix + while true do + prefix = utfchar(random(65,90),random(65,90),random(65,90),random(65,90),random(65,90),random(65,90)) + if not prefixes[prefix] then + prefixes[prefix] = true + break + end + end + return prefix .. "+" .. name + end + +end + +-- Map file mess. + +local loadmapfile, loadmapline, getmapentry do + + -- We only need to pick up the filename and optionally the enc file + -- as we only use them for old school virtual math fonts. We might as + -- we drop this completely. + + local find, match, splitlines = string.find, string.match, string.splitlines + + + local mappings = { } + + loadmapline = function(n) + if trace_fonts then + report_fonts("mapline: %s",n) + end + local name, fullname, encfile, pfbfile = match(n,"(%S+)%s+(%S+).-<(.-%.enc).-<(.-%.pfb)") + if name then + mappings[name] = { fullname, encfile, pfbfile } + end + end + + loadmapfile = function(n) + local okay, data = resolvers.loadbinfile(n,"map") + if okay and data then + data = splitlines(data) + for i=1,#data do + local d = data[i] + if d ~= "" and not find(d,"^[#%%]") then + loadmapline(d) + end + end + end + end + + getmapentry = function(n) + local n = file.nameonly(n) + local m = mappings[n] + if m then + local encfile = m[2] + local encoding = fonts.encodings.load(encfile) + if not encoding then + return + end + local pfbfile = resolvers.findfile(m[3],"pfb") + if not pfbfile or pfbfile == "" then + return + end + return encoding, pfbfile, encfile + end + end + + lpdf.getmapentry = getmapentry + +end + +-- The three writers: opentype, truetype and type1. + +local mainwriters = { } + +do + + -- advh = os2.ascender - os2.descender + -- tsb = default_advh - os2.ascender + + -- truetype has the following tables: + + -- head : mandate + -- hhea : mandate + -- vhea : mandate + -- hmtx : mandate + -- maxp : mandate + -- glyf : mandate + -- loca : mandate + -- + -- cvt : if needed (but we flatten) + -- fpgm : if needed (but we flatten) + -- prep : if needed (but we flatten) + -- PCLT : if needed (but we flatten) + -- + -- name : not needed for T2: backend does that + -- post : not needed for T2: backend does that + -- OS/2 : not needed for T2: backend does that + -- cmap : not needed for T2: backend does that + + local streams = utilities.streams + local openstring = streams.openstring + local readcardinal2 = streams.readcardinal2 + ----- readcardinal4 = streams.readcardinal4 + + local otfreaders = fonts.handlers.otf.readers + + local function readcardinal4(f) -- this needs to be sorted out + local a = readcardinal2(f) + local b = readcardinal2(f) + if a and b then + return a * 0x10000 + b + end + end + + -- -- -- + + local tablereaders = { } + local tablewriters = { } + local tablecreators = { } + local tableloaders = { } + + local openfontfile, closefontfile, makefontfile, makemetadata do + + local details = { + details = true, + platformnames = true, + platformextras = true, + } + + -- .022 sec on luatex manual, neglectable: + + -- local function checksum(data) + -- local s = openstring(data) + -- local n = 0 + -- local d = #data + -- while true do + -- local c = readcardinal4(s) + -- if c then + -- n = (n + c) % 0x100000000 + -- else + -- break + -- end + -- end + -- return n + -- end + + local function checksum(data) + local s = openstring(data) + local n = 0 + local d = #data + while true do + local a = readcardinal2(s) + local b = readcardinal2(s) + if b then + n = (n + a * 0x10000 + b) % 0x100000000 + else + break + end + end + return n + end + + openfontfile = function(details) + return { + offset = 0, + order = { }, + used = { }, + details = details, + streams = details.streams, + } + end + + closefontfile = function(fontfile) + for k, v in next, fontfile do + fontfile[k] = nil -- so it can be collected asap + end + end + + local metakeys = { + "uniqueid", "version", + "copyright", "license", "licenseurl", + "manufacturer", "vendorurl", + "family", "subfamily", + "typographicfamily", "typographicsubfamily", + "fullname", "postscriptname", + } + + local template = [[ + + + + + +%s + + + + +]] + + makemetadata = function(fontfile) + local names = fontfile.streams.names + local list = { } + local f_name = formatters["%s"] + for i=1,#metakeys do + local m = metakeys[i] + local n = names[m] + if n then + list[#list+1] = f_name(m,n,m) + end + end + return format(template,concat(list,"\n")) + end + + makefontfile = function(fontfile) + local order = fontfile.order + local used = fontfile.used + local count = 0 + for i=1,#order do + local tag = order[i] + local data = fontfile[tag] + if data and #data > 0 then + count = count + 1 + else + fontfile[tag] = false + end + end + local offset = 12 + (count * 16) + local headof = 0 + local list = { + "" -- placeholder + } + local i = 1 + local k = 0 + while i <= count do + i = lshift(i,1) + k = k + 1 + end + local searchrange = lshift(i,3) + local entryselector = k - 1 + local rangeshift = lshift(count,4) - lshift(i,3) + local index = { + tocardinal4(0x00010000), -- tables.version + tocardinal2(count), + tocardinal2(searchrange), + tocardinal2(entryselector), + tocardinal2(rangeshift), + } + -- + local ni = #index + local nl = #list + for i=1,#order do + local tag = order[i] + local data = fontfile[tag] + if data then + local csum = checksum(data) + local dlength = #data + local length = idiv(dlength+3,4) * 4 + local padding = length - dlength + nl = nl + 1 ; list[nl] = data + for i=1,padding do + nl = nl + 1 ; list[nl] = "\0" + end + if #tag == 3 then + tag = tag .. " " + end + ni = ni + 1 ; index[ni] = tag -- must be 4 chars + ni = ni + 1 ; index[ni] = tocardinal4(csum) + ni = ni + 1 ; index[ni] = tocardinal4(offset) + ni = ni + 1 ; index[ni] = tocardinal4(dlength) + used[i] = offset -- not used + if tag == "head" then + headof = offset + end + offset = offset + length + end + end + list[1] = concat(index) + local off = #list[1] + headof + 1 + 8 + list = concat(list) + local csum = (0xB1B0AFBA - checksum(list)) % 0x100000000 + list = sub(list,1,off-1) .. tocardinal4(csum) .. sub(list,off+4,#list) + return list + end + + local function register(fontfile,name) + local u = fontfile.used + local o = fontfile.order + if not u[name] then + o[#o+1] = name + u[name] = true + end + end + + local function create(fontfile,name) + local t = { } + fontfile[name] = t + return t + end + + local function write(fontfile,name) + local t = fontfile[name] + if not t then + return + end + register(fontfile,name) + if type(t) == "table" then + if t[0] then + fontfile[name] = concat(t,"",0,#t) + elseif #t > 0 then + fontfile[name] = concat(t) + else + fontfile[name] = false + end + end + end + + tablewriters.head = function(fontfile) + register(fontfile,"head") + local t = fontfile.streams.fontheader + fontfile.head = concat { + tocardinal4(t.version), + tocardinal4(t.fontversionnumber), + tocardinal4(t.checksum), + tocardinal4(t.magic), + tocardinal2(t.flags), + tocardinal2(t.units), + tocardinal8(t.created), + tocardinal8(t.modified), + tocardinal2(t.xmin), + tocardinal2(t.ymin), + tocardinal2(t.xmax), + tocardinal2(t.ymax), + tocardinal2(t.macstyle), + tocardinal2(t.smallpixels), + tocardinal2(t.directionhint), + tocardinal2(t.indextolocformat), + tocardinal2(t.glyphformat), + } + end + + tablewriters.hhea = function(fontfile) + register(fontfile,"hhea") + local t = fontfile.streams.horizontalheader + local n = t and fontfile.nofglyphs or 0 + fontfile.hhea = concat { + tocardinal4(t.version), + tocardinal2(t.ascender), + tocardinal2(t.descender), + tocardinal2(t.linegap), + tocardinal2(t.maxadvancewidth), + tocardinal2(t.minleftsidebearing), + tocardinal2(t.minrightsidebearing), + tocardinal2(t.maxextent), + tocardinal2(t.caretsloperise), + tocardinal2(t.caretsloperun), + tocardinal2(t.caretoffset), + tocardinal2(t.reserved_1), + tocardinal2(t.reserved_2), + tocardinal2(t.reserved_3), + tocardinal2(t.reserved_4), + tocardinal2(t.metricdataformat), + tocardinal2(n) -- t.nofmetrics + } + end + + tablewriters.vhea = function(fontfile) + local t = fontfile.streams.verticalheader + local n = t and fontfile.nofglyphs or 0 + register(fontfile,"vhea") + fontfile.vhea = concat { + tocardinal4(t.version), + tocardinal2(t.ascender), + tocardinal2(t.descender), + tocardinal2(t.linegap), + tocardinal2(t.maxadvanceheight), + tocardinal2(t.mintopsidebearing), + tocardinal2(t.minbottomsidebearing), + tocardinal2(t.maxextent), + tocardinal2(t.caretsloperise), + tocardinal2(t.caretsloperun), + tocardinal2(t.caretoffset), + tocardinal2(t.reserved_1), + tocardinal2(t.reserved_2), + tocardinal2(t.reserved_3), + tocardinal2(t.reserved_4), + tocardinal2(t.metricdataformat), + tocardinal2(n) -- t.nofmetrics + } + end + + tablewriters.maxp = function(fontfile) + register(fontfile,"maxp") + local t = fontfile.streams.maximumprofile + local n = fontfile.nofglyphs + -- if fontfile.streams.cffinfo then + -- error + -- end + fontfile.maxp = concat { + tocardinal4(0x00010000), + tocardinal2(n), + tocardinal2(t.points), + tocardinal2(t.contours), + tocardinal2(t.compositepoints), + tocardinal2(t.compositecontours), + tocardinal2(t.zones), + tocardinal2(t.twilightpoints), + tocardinal2(t.storage), + tocardinal2(t.functiondefs), + tocardinal2(t.instructiondefs), + tocardinal2(t.stackelements), + tocardinal2(t.sizeofinstructions), + tocardinal2(t.componentelements), + tocardinal2(t.componentdepth), + } + end + + tablecreators.loca = function(fontfile) return create(fontfile,"loca") end + tablewriters .loca = function(fontfile) return write (fontfile,"loca") end + + tablecreators.glyf = function(fontfile) return create(fontfile,"glyf") end + tablewriters .glyf = function(fontfile) return write (fontfile,"glyf") end + + tablecreators.hmtx = function(fontfile) return create(fontfile,"hmtx") end + tablewriters .hmtx = function(fontfile) return write (fontfile,"hmtx") end + + tablecreators.vmtx = function(fontfile) return create(fontfile,"vmtx") end + tablewriters .vmtx = function(fontfile) return write (fontfile,"vmtx") end + + tableloaders .cmap = function(fontfile) return read (fontfile,"cmap") end + tablewriters .cmap = function(fontfile) return write (fontfile,"cmap") end + + tableloaders .name = function(fontfile) return read (fontfile,"name") end + tablewriters .name = function(fontfile) return write (fontfile,"name") end + + tableloaders .post = function(fontfile) return read (fontfile,"post") end + tablewriters .post = function(fontfile) return write (fontfile,"post") end + + end + + mainwriters["truetype"] = function(details) + -- + local fontfile = openfontfile(details) + local basefontname = details.basefontname + local streams = details.streams + local blobs = streams.streams + local fontheader = streams.fontheader + local horizontalheader = streams.horizontalheader + local verticalheader = streams.verticalheader + local maximumprofile = streams.maximumprofile + local names = streams.names + local descriptions = details.rawdata.descriptions + local metadata = details.rawdata.metadata + local indices = details.indices + local metabbox = { fontheader.xmin, fontheader.ymin, fontheader.xmax, fontheader.ymax } + local indices, + minindex, + maxindex = collectindices(descriptions,indices) + local glyphstreams = tablecreators.glyf(fontfile) + local locations = tablecreators.loca(fontfile) + local horizontals = tablecreators.hmtx(fontfile) + local verticals = tablecreators.vmtx(fontfile) + -- + local zero2 = tocardinal2(0) + local zero4 = tocardinal4(0) + -- + local horizontal = horizontalheader.nofmetrics > 0 + local vertical = verticalheader.nofmetrics > 0 + -- + local streamoffset = 0 + local lastoffset = zero4 + local g, h, v = 0, 0, 0 + -- + -- todo: locate notdef + -- + if minindex > 0 then + local blob = blobs[0] + if blob and #blob > 0 then + locations[0] = lastoffset + g = g + 1 ; glyphstreams[g] = blob + h = h + 1 ; horizontals [h] = zero4 + if vertical then + v = v + 1 ; verticals[v] = zero4 + end + streamoffset = streamoffset + #blob + lastoffset = tocardinal4(streamoffset) + else + report_fonts("missing .notdef in font %a",basefontname) + end + -- todo: use a rep for h/v + for index=1,minindex-1 do + locations[index] = lastoffset + h = h + 1 ; horizontals[h] = zero4 + if vertical then + v = v + 1 ; verticals[v] = zero4 + end + end + end + for index=minindex,maxindex do + locations[index] = lastoffset + local data = indices[index] + if data then + local blob = blobs[index] -- we assume padding + if blob and #blob > 0 then + g = g + 1 ; glyphstreams[g] = blob + h = h + 1 ; horizontals [h] = tocardinal2(data.width or 0) + h = h + 1 ; horizontals [h] = tocardinal2(data.boundingbox[1]) + if vertical then + v = v + 1 ; verticals[v] = tocardinal2(data.height or 0) + v = v + 1 ; verticals[v] = tocardinal2(data.boundingbox[3]) + end + streamoffset = streamoffset + #blob + lastoffset = tocardinal4(streamoffset) + else + h = h + 1 ; horizontals[h] = zero4 + if vertical then + v = v + 1 ; verticals[v] = zero4 + end + report_fonts("missing blob for index %i in font %a",index,basefontname) + end + else + h = h + 1 ; horizontals[h] = zero4 + if vertical then + v = v + 1 ; verticals[v] = zero4 + end + end + end + locations[maxindex+1] = lastoffset -- cf spec + -- + local nofglyphs = maxindex + 1 -- include zero + -- + fontheader.checksum = 0 + fontheader.indextolocformat = 1 + maximumprofile.nofglyphs = nofglyphs + -- + fontfile.format = "tff" + fontfile.basefontname = basefontname + fontfile.nofglyphs = nofglyphs + -- + tablewriters.head(fontfile) + tablewriters.hhea(fontfile) + if vertical then + tablewriters.vhea(fontfile) + end + tablewriters.maxp(fontfile) + + tablewriters.loca(fontfile) + tablewriters.glyf(fontfile) + + tablewriters.hmtx(fontfile) + if vertical then + tablewriters.vmtx(fontfile) + end + -- + local fontdata = makefontfile(fontfile) + local fontmeta = makemetadata(fontfile) + -- + fontfile = closefontfile(fontfile) + -- + local units = metadata.units + local basefont = pdfconstant(basefontname) + local widths = widtharray(details,indices,maxindex,units) + local object = details.objectnumber + local tounicode = tounicodedictionary(details,indices,maxindex,basefontname,true) + local tocidset = tocidsetdictionary(indices,minindex,maxindex) + local metabbox = metadata.boundingbox or { 0, 0, 0, 0 } + local fontbbox = pdfarray { unpack(metabbox) } + local ascender = metadata.ascender + local descender = metadata.descender + local capheight = metadata.capheight or fontbbox[4] + local stemv = metadata.weightclass + local italicangle = metadata.italicangle + local xheight = metadata.xheight or fontbbox[4] + -- + if stemv then + stemv = (stemv/65)^2 + 50 + end + -- + local function scale(n) + if n then + return round((n) * 10000 / units) / 10 + else + return 0 + end + end + -- + local reserved = pdfreserveobject() + local child = pdfdictionary { + Type = pdfconstant("Font"), + Subtype = pdfconstant("CIDFontType2"), + BaseFont = basefont, + FontDescriptor = pdfreference(reserved), + W = pdfreference(pdfflushobject(widths)), + CIDToGIDMap = pdfconstant("Identity"), + CIDSystemInfo = pdfdictionary { + Registry = pdfstring("Adobe"), + Ordering = pdfstring("Identity"), + Supplement = 0, + } + } + local descendants = pdfarray { + pdfreference(pdfflushobject(child)), + } + local descriptor = pdfdictionary { + Type = pdfconstant("FontDescriptor"), + FontName = basefont, + Flags = 4, + FontBBox = fontbbox, + Ascent = scale(ascender), + Descent = scale(descender), + ItalicAngle = round(italicangle or 0), + CapHeight = scale(capheight), + StemV = scale(stemv), + XHeight = scale(xheight), + FontFile2 = pdfreference(pdfflushstreamobject(fontdata)), + CIDSet = tocidset, + Metadata = fontmeta and pdfreference(pdfflushstreamobject(fontmeta)) or nil, + } + local parent = pdfdictionary { + Type = pdfconstant("Font"), + Subtype = pdfconstant("Type0"), + Encoding = pdfconstant(details.properties.writingmode == "vertical" and "Identity-V" or "Identity-H"), + BaseFont = basefont, + DescendantFonts = descendants, + ToUnicode = pdfreference(pdfflushstreamobject(tounicode)), + } + pdfflushobject(reserved,descriptor) + pdfflushobject(object,parent) + -- + -- if trace_details then + -- local name = "temp.ttf" + -- report_fonts("saving %a",name) + -- io.savedata(name,fontdata) + -- inspect(fonts.handlers.otf.readers.loadfont(name)) + -- end + -- + end + + do + -- todo : cff2 + + local details = { + details = true, + platformnames = true, + platformextras = true, + } + + tablecreators.cff = function(fontfile) + fontfile.charstrings = { } + fontfile.charmappings = { } + fontfile.cffstrings = { } + fontfile.cffhash = { } + return fontfile.charstrings , fontfile.charmappings + end + + local todictnumber, todictreal, todictinteger, todictoffset do + + local maxnum = 0x7FFFFFFF + local minnum = - 0x7FFFFFFF - 1 + local epsilon = 1.0e-5 + + local int2tag = "\28" + local int4tag = "\29" + local realtag = "\30" + + todictinteger = function(n) + if not n then + return char(band(139,0xFF)) + elseif n >= -107 and n <= 107 then + return char(band(n + 139,0xFF)) + elseif n >= 108 and n <= 1131 then + n = 0xF700 + n - 108 + return char(band(rshift(n,8),0xFF),band(n,0xFF)) + elseif n >= -1131 and n <= -108 then + n = 0xFB00 - n - 108 + return char(band(rshift(n,8),0xFF),band(n,0xFF)) + elseif n >= -32768 and n <= 32767 then + -- return int2tag .. tointeger2(n) + return char(28,extract(n,8,8),extract(n,0,8)) + else + -- return int4tag .. tointeger4(n) + return char(29,extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) + end + end + + -- -- not called that often + -- + -- local encoder = readers.cffencoder + -- + -- todictinteger = function(n) + -- if not n then + -- return encoder[0] + -- elseif n >= -1131 and n <= 1131 then + -- return encoder[n] + -- elseif n >= -32768 and n <= 32767 then + -- -- return int2tag .. tointeger2(n) + -- return char(28,extract(n,8,8),extract(n,0,8)) + -- else + -- -- return int4tag .. tointeger4(n) + -- return char(29,extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) + -- end + -- end + + todictoffset = function(n) + return int4tag .. tointeger4(n) + end + + local e = false + local z = byte("0") + local dp = 10 + local ep = 11 + local em = 12 + local mn = 14 + local es = 15 + + local fg = formatters["%g"] + + todictreal = function(v) + local s = fg(v) + local t = { [0] = realtag } + local n = 0 + for s in gmatch(s,".") do + if s == "e" or s == "E" then + e = true + elseif s == "+" then + -- skip + elseif s == "-" then + n = n + 1 + if e then + t[n] = em + e = false + else + t[n] = mn + end + else + if e then + n = n + 1 + t[n] = ep + e = false + end + n = n + 1 + if s == "." then + t[n] = dp + else + t[n] = byte(s) - z + end + end + end + n = n + 1 + t[n] = es + if (n % 2) ~= 0 then + n = n + 1 + t[n] = es + end + local j = 0 + for i=1,n,2 do + j = j + 1 + t[j] = char(t[i]*0x10+t[i+1]) + end + t = concat(t,"",0,j) + return t + end + + todictnumber = function(n) + if not n or n == 0 then + return todictinteger(0) + elseif (n > maxnum or n < minnum or (abs(n - round(n)) > epsilon)) then + return todictreal(n) + else + return todictinteger(n) + end + end + + end + + local todictkey = char + + local function todictstring(fontfile,value) + if not value then + value = "" + end + local s = fontfile.cffstrings + local h = fontfile.cffhash + local n = h[value] + if not n then + n = #s + 1 + s[n] = value + h[value] = n + end + return todictinteger(390+n) + end + + local function todictboolean(b) + return todictinteger(b and 1 or 0) + end + + local function todictdeltas(t) + local r = { } + for i=1,#t do + r[i] = todictnumber(t[i]-(t[i-1] or 0)) + end + return concat(r) + end + + local function todictarray(t) + local r = { } + for i=1,#t do + r[i] = todictnumber(t[i]) + end + return concat(r) + end + + local function writestring(target,source,offset,what) + target[#target+1] = source + -- report_fonts("string : %-11s %06i # %05i",what,offset,#source) + return offset + #source + end + + local function writetable(target,source,offset,what) + source = concat(source) + target[#target+1] = source + -- report_fonts("table : %-11s %06i # %05i",what,offset,#source) + return offset + #source + end + + local function writeindex(target,source,offset,what) + local n = #source + local t = #target + t = t + 1 ; target[t] = tocardinal2(n) + if n > 0 then + local data = concat(source) + local size = #data -- assume the worst + local offsetsize, tocardinal + if size < 0xFF then + offsetsize, tocardinal = 1, tocardinal1 + elseif size < 0xFFFF then + offsetsize, tocardinal = 2, tocardinal2 + elseif size < 0xFFFFFF then + offsetsize, tocardinal = 3, tocardinal3 + elseif size < 0xFFFFFFFF then + offsetsize, tocardinal = 4, tocardinal4 + end + -- report_fonts("index : %-11s %06i # %05i (%i entries with offset size %i)",what,offset,#data,n,offsetsize) + offset = offset + 2 + 1 + (n + 1) * offsetsize + size + -- bytes per offset + t = t + 1 ; target[t] = tocardinal1(offsetsize) + -- list of offsets (one larger for length calculation) + local offset = 1 -- mandate + t = t + 1 ; target[t] = tocardinal(offset) + for i=1,n do + offset = offset + #source[i] + t = t + 1 ; target[t] = tocardinal(offset) + end + t = t + 1 ; target[t] = data + else + -- report_fonts("index : %-11s %06i # %05i (no entries)",what,offset,0) + offset = offset + 2 + end + -- print("offset",offset,#concat(target)) + return offset + end + + tablewriters.cff = function(fontfile) + -- + local streams = fontfile.streams + local cffinfo = streams.cffinfo or { } + local names = streams.names or { } + local fontheader = streams.fontheader or { } + local basefontname = fontfile.basefontname + -- + local offset = 0 + local dictof = 0 + local target = { } + -- + local charstrings = fontfile.charstrings + local nofglyphs = #charstrings + 1 + local fontmatrix = { 0.001, 0, 0, 0.001, 0, 0 } -- todo + local fontbbox = fontfile.fontbbox + local defaultwidth = cffinfo.defaultwidth or 0 + local nominalwidth = cffinfo.nominalwidth or 0 + local bluevalues = cffinfo.bluevalues + local otherblues = cffinfo.otherblues + local familyblues = cffinfo.familyblues + local familyotherblues = cffinfo.familyotherblues + local bluescale = cffinfo.bluescale + local blueshift = cffinfo.blueshift + local bluefuzz = cffinfo.bluefuzz + local stdhw = cffinfo.stdhw + local stdvw = cffinfo.stdvw + -- + if defaultwidth == 0 then defaultwidth = nil end + if nomimalwidth == 0 then nominalwidth = nil end + if bluevalues then bluevalues = todictarray(bluevalues) end + if otherblues then otherblues = todictarray(otherblues) end + if familyblues then familyblues = todictarray(familyblues) end + if familyotherblues then familyotherblues = todictarray(familyotherblues) end + if bluescale then bluescale = todictnumber(bluescale) end + if blueshift then blueshift = todictnumber(blueshift) end + if bluefuzz then bluefuzz = todictnumber(bluefuzz) end + if stdhw then stdhw = todictdeltas(stdhw) end + if stdvw then stdvw = todictdeltas(stdvw) end + -- + local fontversion = todictstring(fontfile,fontheader.fontversion or "uknown version") + local familyname = todictstring(fontfile,cffinfo.familyname or names.family or basefontname) + local fullname = todictstring(fontfile,cffinfo.fullname or basefontname) + local weight = todictstring(fontfile,cffinfo.weight or "Normal") + local fontbbox = todictarray(fontbbox) + local strokewidth = todictnumber(cffinfo.strokewidth) + local monospaced = todictboolean(cffinfo.monospaced) + local italicangle = todictnumber(cffinfo.italicangle) + local underlineposition = todictnumber(cffinfo.underlineposition) + local underlinethickness = todictnumber(cffinfo.underlinethickness) + local charstringtype = todictnumber(2) + local fontmatrix = todictarray(fontmatrix) + local ros = todictstring(fontfile,"Adobe") -- registry + .. todictstring(fontfile,"Identity") -- identity + .. todictnumber(0) -- supplement + local cidcount = todictnumber(fontfile.nofglyphs) + local fontname = todictstring(fontfile,basefontname) + local fdarrayoffset = todictoffset(0) + local fdselectoffset = todictoffset(0) + local charstringoffset = todictoffset(0) + local charsetoffset = todictoffset(0) + local privateoffset = todictoffset(0) + -- + local defaultwidthx = todictnumber(defaultwidth) + local nominalwidthx = todictnumber(nominalwidth) + local private = "" + .. (defaultwidthx and (defaultwidthx .. todictkey(20)) or "") + .. (nominalwidthx and (nominalwidthx .. todictkey(21)) or "") + .. (bluevalues and (bluevalues .. todictkey(6)) or "") + .. (otherblues and (otherblues .. todictkey(7)) or "") + .. (familyblues and (familyblues .. todictkey(8)) or "") + .. (familyotherblues and (familyotherblues .. todictkey(9)) or "") + .. (bluescale and (bluescale .. todictkey(12,9)) or "") + .. (blueshift and (blueshift .. todictkey(12,10)) or "") + .. (bluefuzz and (bluefuzz .. todictkey(12,11)) or "") + .. (stdhw and (stdhw .. todictkey(12,12)) or "") + .. (stdvw and (stdvw .. todictkey(12,13)) or "") + local privatesize = todictnumber(#private) + local privatespec = privatesize .. privateoffset + -- + -- header (fixed @ 1) + -- + local header = + tocardinal1(1) -- major + .. tocardinal1(0) -- minor + .. tocardinal1(4) -- header size + .. tocardinal1(4) -- offset size + -- + offset = writestring(target,header,offset,"header") + -- + -- name index (fixed @ 2) (has to be sorted) + -- + local names = { + basefontname, + } + -- + offset = writeindex(target,names,offset,"names") + -- + -- topdict index (fixed @ 3) + -- + local topvars = + charstringoffset .. todictkey(17) + .. charsetoffset .. todictkey(15) + .. fdarrayoffset .. todictkey(12,36) + .. fdselectoffset .. todictkey(12,37) + .. privatespec .. todictkey(18) + -- + local topdict = { + ros .. todictkey(12,30) -- first + .. cidcount .. todictkey(12,34) + .. familyname .. todictkey( 3) + .. fullname .. todictkey( 2) + .. weight .. todictkey( 4) + .. fontbbox .. todictkey( 5) + .. monospaced .. todictkey(12, 1) + .. italicangle .. todictkey(12, 2) + .. underlineposition .. todictkey(12, 3) + .. underlinethickness .. todictkey(12, 4) + .. charstringtype .. todictkey(12, 6) + .. fontmatrix .. todictkey(12, 7) + .. strokewidth .. todictkey(12, 8) + .. topvars + } + -- + offset = writeindex(target,topdict,offset,"topdict") + dictof = #target + -- + -- string index (fixed @ 4) + -- + offset = writeindex(target,fontfile.cffstrings,offset,"strings") + -- + -- global subroutine index (fixed @ 5) + -- + offset = writeindex(target,{},offset,"globals") + -- + -- Encoding (cff1) + -- + -- offset = writeindex(target,{},offset,"encoding") + -- + -- Charsets + -- + charsetoffset = todictoffset(offset) + offset = writetable(target,fontfile.charmappings,offset,"charsets") + -- + -- fdselect + -- + local fdselect = + tocardinal1(3) -- format + .. tocardinal2(1) -- n of ranges + -- entry 1 + .. tocardinal2(0) -- first gid + .. tocardinal1(0) -- fd index + -- entry 2 +-- .. tocardinal2(fontfile.sparsemax-1) -- sentinel + .. tocardinal2(fontfile.sparsemax) -- sentinel + -- + fdselectoffset = todictoffset(offset) + offset = writestring(target,fdselect,offset,"fdselect") + -- + -- charstrings + -- + charstringoffset = todictoffset(offset) + offset = writeindex(target,charstrings,offset,"charstrings") + -- + -- font dict + -- + -- offset = writeindex(target,{},offset,"fontdict") + -- + -- private + -- + privateoffset = todictoffset(offset) + privatespec = privatesize .. privateoffset + offset = writestring(target,private,offset,"private") + -- + local fdarray = { + fontname .. todictkey(12,38) + .. privatespec .. todictkey(18) + } + fdarrayoffset = todictoffset(offset) + offset = writeindex(target,fdarray,offset,"fdarray") + -- + topdict = target[dictof] + topdict = sub(topdict,1,#topdict-#topvars) + topvars = + charstringoffset .. todictkey(17) + .. charsetoffset .. todictkey(15) + .. fdarrayoffset .. todictkey(12,36) + .. fdselectoffset .. todictkey(12,37) + .. privatespec .. todictkey(18) + target[dictof] = topdict .. topvars + -- + target = concat(target) + -- if trace_details then + -- local name = "temp.cff" + -- report_fonts("saving %a",name) + -- io.savedata(name,target) + -- inspect(fonts.handlers.otf.readers.cffcheck(name)) + -- end + return target + end + + end + + -- todo: check widths (missing a decimal) + + mainwriters["opentype"] = function(details) + -- + local fontfile = openfontfile(details) + local basefontname = details.basefontname + local streams = details.streams + local blobs = streams.streams + local fontheader = streams.fontheader + local maximumprofile = streams.maximumprofile + local names = streams.names + local descriptions = details.rawdata.descriptions + local metadata = details.rawdata.metadata + local indices = details.indices + local metabbox = { fontheader.xmin, fontheader.ymin, fontheader.xmax, fontheader.ymax } + local correction = 1 + + -- (*) We share code with type1 and when we have old school tfm with + -- pfb but without descriptions we're kind of toast. + + if not descriptions or not next(descriptions) then + -- This is good enough, we only need indices and widths. + descriptions = details.fontdata.characters + -- This is a hack, we have no basepoints. + correction = details.fontdata.parameters.size / 1000 + -- And this needs checking. + correction = correction * bpfactor / ptfactor + metadata = { } + end + + -- + + local indices, + minindex, + maxindex = collectindices(descriptions,indices) + local streamoffset = 0 + local glyphstreams, + charmappings = tablecreators.cff(fontfile) + -- + local zero2 = tocardinal2(0) + local zero4 = tocardinal4(0) + -- + -- we need to locate notdef (or store its unicode someplace) + -- + local blob = blobs[0] or "\14" + local sparsemax = 1 + local lastoffset = zero4 + glyphstreams[sparsemax] = blob + charmappings[sparsemax] = tocardinal1(0) -- format 0 + streamoffset = streamoffset + #blob + lastoffset = tocardinal4(streamoffset) + if minindex == 0 then + minindex = 1 + end + for index=minindex,maxindex do + if indices[index] then + local blob = blobs[index] or "\14" + sparsemax = sparsemax + 1 + glyphstreams[sparsemax] = blob + charmappings[sparsemax] = tocardinal2(index) + streamoffset = streamoffset + #blob + lastoffset = tocardinal4(streamoffset) + end + end + -- + fontfile.nofglyphs = maxindex + 1 + fontfile.sparsemax = sparsemax + fontfile.format = "cff" + fontfile.basefontname = basefontname + fontfile.fontbbox = metabbox + -- + local fontdata = tablewriters.cff(fontfile) + local fontmeta = makemetadata(fontfile) + -- + fontfile = closefontfile(fontfile) + -- + local units = fontheader.units or metadata.units + + local basefont = pdfconstant(basefontname) + local widths = widtharray(details,indices,maxindex,units * correction) + local object = details.objectnumber + local tounicode = tounicodedictionary(details,indices,maxindex,basefontname,true) + local tocidset = tocidsetdictionary(indices,minindex,maxindex) + local fontbbox = pdfarray { unpack(metabbox) } + local ascender = metadata.ascender or 0 + local descender = metadata.descender or 0 + local capheight = metadata.capheight or fontbbox[4] + local stemv = metadata.weightclass + local italicangle = metadata.italicangle + local xheight = metadata.xheight or fontbbox[4] + if stemv then + stemv = (stemv/65)^2 + 50 + else +-- stemv = 2 + end + -- + local function scale(n) + if n then + return round((n) * 10000 / units) / 10 + else + return 0 + end + end + -- + local reserved = pdfreserveobject() + local child = pdfdictionary { + Type = pdfconstant("Font"), + Subtype = pdfconstant("CIDFontType0"), + BaseFont = basefont, + FontDescriptor = pdfreference(reserved), + W = pdfreference(pdfflushobject(widths)), + CIDSystemInfo = pdfdictionary { + Registry = pdfstring("Adobe"), + Ordering = pdfstring("Identity"), + Supplement = 0, + } + } + local descendants = pdfarray { + pdfreference(pdfflushobject(child)), + } + local fontstream = pdfdictionary { + Subtype = pdfconstant("CIDFontType0C"), + } + local descriptor = pdfdictionary { + Type = pdfconstant("FontDescriptor"), + FontName = basefont, + Flags = 4, + FontBBox = fontbbox, + Ascent = scale(ascender), + Descent = scale(descender), + ItalicAngle = round(italicangle or 0), + CapHeight = scale(capheight), + StemV = scale(stemv), + XHeight = scale(xheight), + CIDSet = tocidset, + FontFile3 = pdfreference(pdfflushstreamobject(fontdata,fontstream())), + Metadata = fontmeta and pdfreference(pdfflushstreamobject(fontmeta)) or nil, + } + local parent = pdfdictionary { + Type = pdfconstant("Font"), + Subtype = pdfconstant("Type0"), + Encoding = pdfconstant(details.properties.writingmode == "vertical" and "Identity-V" or "Identity-H"), + BaseFont = basefont, + DescendantFonts = descendants, + ToUnicode = pdfreference(pdfflushstreamobject(tounicode)), + } + pdfflushobject(reserved,descriptor) + pdfflushobject(object,parent) + end + + mainwriters["type1"] = function(details) + -- We abuse the cff includer which is ok but for special cases like + -- tfm -> pfb we don't have the right descriptions and scale so this + -- is why we cheat elsewhere. Maybe I should just drop that kind of + -- support and assume afm files to be present. See (*) above. + local s = details.streams + local m = details.rawdata.metadata + if m then + local h = s.horizontalheader + local c = s.cffinfo + local n = s.names + h.ascender = m.ascender or h.ascender + h.descender = m.descender or h.descender + n.copyright = m.copyright or n.copyright + n.family = m.familyname or n.familyname + n.fullname = m.fullname or n.fullname + n.fontname = m.fontname or n.fontname + n.subfamily = m.subfamilyname or n.subfamilyname + n.version = m.version or n.version + setmetatableindex(h,m) + setmetatableindex(c,m) + setmetatableindex(n,m) + end + mainwriters["opentype"](details) + end + + do + + -- The methods might become plugins. + + local methods = { } + + local pdfimage = lpdf.epdf.image + local openpdf = pdfimage.open + local closepdf = pdfimage.close + local copypage = pdfimage.copy + + 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_xy = formatters["%.6N 0 d0 1 0 0 1 %.6N %.6N cm /%s Do"] + local f_image_c = formatters["/%s Do"] + local f_image_c_xy = formatters["%.6N 0 0 %.6N %.6N %.6N cm /%s Do"] + local f_image_w = formatters["%.6N 0 d0 %s"] + local f_image_d = formatters["%.6N 0 d0 1 0 0 1 0 %.6N cm /%s Do"] + local f_stream = formatters["%.6N 0 d0 %s"] + local f_stream_c = formatters["%.6N 0 0 0 0 0 d1 %s"] + local f_stream_d = formatters["%.6N 0 d0 1 0 0 1 0 %.6N 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. We also need to + -- make sure that we use bytes as index in the page stream as well as in the + -- tounicode vector. + + local c_notdef = nil + local r_notdef = nil + local w_notdef = nil + local fontbbox = nil + + -- pk inclusion (not really tested but not really used either) + + function methods.pk(filename) + local pkfullname = resolvers.findpk(basedfontname,resolution) + if not pkfullname or pkfullname == "" then + return + end + local readers = fonts.handlers.tfm.readers + local result = readers.loadpk(pkfullname) + local convert = readers.pktopdf + if not result or result.error then + return + end + local resolution = 600 + local widthfactor = resolution / 72 + local scalefactor = 72 / resolution / 10 + local factor = widthfactor / 65536 + local function pktopdf(glyph,data) + return convert(glyph,data,factor) -- return pdfcode, width + end + return result.glyphs, scalefactor, pktopdf, false, false + end + + -- pdf inclusion + + local used = setmetatableindex("table") + + function methods.pdf(filename,details) + local properties = details.properties + local pdfshapes = properties.indexdata[1] + local pdfdoc = openpdf(pdfshapes.filename) + 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 useddoc = used[pdfdoc] + local function pdftopdf(glyph,data) + local width = (data.width or 0) * factor + local image = useddoc[glyph] + local reference = nil + if not image then + image = embedimage(copypage(pdfdoc,glyph)) + nofglyphs = nofglyphs + 1 + local name = f_glyph(nofglyphs) + local stream = nil + if fixdepth then + local depth = data.depth or 0 + local height = data.height or 0 + if depth ~= 0 or height ~= 0 then + local d = data.dropin.descriptions[data.index] + local b = d.boundingbox + local l = b[1] + local r = b[3] + local w = r - l + local scale = w / d.width + local x = l + local y = - b[4] - b[2] - d.depth + local scale = w / (image.width * bpfactor) + stream = f_image_c_xy(scale,scale,x,y,name) + else + stream = f_image_c(name) + end + else + stream = f_image_c(name) + end + useddoc[glyph] = image + image.embedded_name = name + image.embedded_stream = stream + image.embedded_reference = pdfreference(image.objnum) + end + xforms[image.embedded_name] = image.embedded_reference + return f_image_w(width,image.embedded_stream), width + end + local function closepdf() + -- closepdf(pdfdoc) + end + local function getresources() + return pdfdictionary { XObject = xforms } + end + return pdfshapes, 1/units, pdftopdf, closepdf, getresources + end + end + + -- mps inclusion + + local decompress = gzip.decompress + local metapost = metapost + local simplemprun = metapost.simple + local setparameterset = metapost.setparameterset + + function methods.mps(filename,details) + local properties = details.properties + local parameters = details.parameters + local mpshapes = properties.indexdata[1] -- indexdata will change + if mpshapes then + local scale = 10 * parameters.size/parameters.designsize + local units = mpshapes.units or parameters.units + local factor = units * bpfactor / scale + local fixdepth = mpshapes.fixdepth + local usecolor = mpshapes.usecolor + local specification = mpshapes.specification + local shapedefinitions = mpshapes.shapes + local instance = mpshapes.instance + -- + simplemprun(instance,"begingroup;",true,true) + setparameterset("mpsfont",specification) + if shapedefinitions then + local preamble = shapedefinitions.parameters.preamble + if preamble then + simplemprun(instance,preamble,true,true) + end + end + -- + local function mpstopdf(mp,data) + local width = data.width + if decompress then + mp = decompress(mp) + end + local pdf = simplemprun(instance,mp,true) -- can be sped up, minifun + local width = width * factor + if usecolor then + return f_stream_c(width,pdf), width + elseif 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 resetmps() + setparameterset("mpsfont") + simplemprun(instance,"endgroup;",true,true) + end + -- + local function getresources() + return lpdf.collectedresources { + serialize = false, + } + end + -- + return mpshapes, 1/units, mpstopdf, resetmps, getresources + end + end + + -- png inclusion + + -- With d1 the image mask is used when given and obeys color. So it is needed for pure bw + -- bitmap fonts, so here we really need d0. + -- + -- Acrobat X pro only seems to see the image mask but other viewers are doing it ok. Acrobat + -- reader crashes. We really need to add a notdef! + + local files = utilities.files + local openfile = files.open + local closefile = files.close + local setposition = files.setposition + local readstring = files.readstring + + function methods.png(filename,details) + local properties = details.properties + local pngshapes = properties.indexdata[1] + if pngshapes then + local parameters = details.parameters + local png = properties.png + local hash = png.hash + local xforms = pdfdictionary() + local nofglyphs = 0 + local scale = 10 * parameters.size/parameters.designsize + local factor = bpfactor / scale + -- local units = parameters.units -- / 1000 + local units = 1000 + local filehandle = openfile(details.filename,true) + local function pngtopdf(glyph,data) + -- local info = graphics.identifiers.png(glyph.data,"string") + local offset = glyph.o + local size = glyph.s + local pdfdata = nil + if offset and size then + setposition(filehandle,offset) + local blob = readstring(filehandle,size) + local info = graphics.identifiers.png(blob,"string") + info.enforcecmyk = pngshapes.enforcecmyk + local image = lpdf.injectors.png(info,"string") + local width = (data.width or 0) * factor + if image then + embedimage(image) + nofglyphs = nofglyphs + 1 + local xoffset = (glyph.x or 0) / units + local yoffset = (glyph.y or 0) / units + local name = f_glyph(nofglyphs) + xforms[name] = pdfreference(image.objnum) + pdfdata = f_image_xy(width,xoffset,yoffset,name) + end + end + return pdfdata or f_stream(width), width + end + local function closepng() + if filehandle then + closefile(filehandle) + end + pngshapes = nil + end + local function getresources() + return pdfdictionary { XObject = xforms } + end + return pngshapes, 1, pngtopdf, closepng, getresources + end + end + + function methods.color(filename,details) + local colrshapes = details.properties.indexdata[1] + local colrvalues = details.properties.indexdata[2] + local usedfonts = { } + local function colrtopdf(description,data) + -- descriptions by index + local colorlist = description.colors + if colorlist then + local dropdata = data.dropin + local dropid = dropdata.properties.id + local dropunits = dropdata.parameters.units -- shared + local descriptions = dropdata.descriptions + usedfonts[dropid] = dropid + local w = description.width or 0 + local s = #colorlist + local l = nil + 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 + if v and l ~= v then + n = n + 1 ; t[n] = v + l = v + end + local e = descriptions[entry.slot] + if e then + n = n + 1 ; t[n] = f_char(dropid,e.index) + end + end + return concat(t," "), w / dropunits + end + end + local function getresources() + return lpdf.collectedresources { + serialize = false, + fonts = usedfonts, + fontprefix = "V", + } + end + return colrshapes, 1, colrtopdf, false, getresources + end + + mainwriters["type3"] = function(details) + local properties = details.properties + local basefontname = details.basefontname or properties.name + local askedmethod = properties.method or "pk" + local method = methods[askedmethod] or methods.pk + if not method then + return + end + local glyphs, scalefactor, glyphtopdf, reset, getresources = method(basedfontname,details) + if not glyphs then + return + end + local parameters = details.parameters + local object = details.objectnumber + local factor = parameters.factor -- normally 1 + local fontmatrix = pdfarray { scalefactor, 0, 0, scalefactor, 0, 0 } + local indices, + minindex, + maxindex = collectindices(details.fontdata.characters,details.indices) + local widths = pdfarray() + local differences = pdfarray() + local charprocs = pdfdictionary() + local basefont = pdfconstant(basefontname) + local d = 0 + local w = 0 + local forcenotdef = minindex > 0 + local lastindex = -0xFF + if forcenotdef then + widths[0] = 0 + minindex = 0 + lastindex = 0 + d = 2 + if not c_notdef then + w_notdef = 0 + c_notdef = pdfconstant(".notdef") + r_notdef = pdfreference(pdfflushstreamobject("0 0 d0")) + end + differences[1] = w_notdef + differences[2] = c_notdef + charprocs[".notdef"] = r_notdef + end + + 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] + if glyph then + local stream, width = glyphtopdf(glyph,data) + if stream then + if index - 1 ~= lastindex then + d = d + 1 differences[d] = index + end + lastindex = index + d = d + 1 differences[d] = pdfconstant(name) + charprocs[name] = pdfreference(pdfflushstreamobject(stream)) + widths[index-minindex+1] = width + end + else + report_fonts("missing glyph %i in type3 font %a",index,basefontname) + end + end + if not fontbbox then + -- The specification permits zero values and these are actually also more + -- robust as then there are no assumptions and no accuracy is needed. + fontbbox = pdfarray { 0, 0, 0, 0 } + end + local encoding = pdfdictionary { + Type = pdfconstant("Encoding"), + Differences = differences, + } + local tounicode = tounicodedictionary(details,indices,maxindex,basefontname,false) + 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"), + FontName = basefont, + Flags = 4, + ItalicAngle = 0, + } + local parent = pdfdictionary { + Type = pdfconstant("Font"), + Subtype = pdfconstant("Type3"), + Name = basefont, + FontBBox = fontbbox, + FontMatrix = fontmatrix, + CharProcs = pdfreference(pdfflushobject(charprocs)), + Encoding = pdfreference(pdfflushobject(encoding)), + FirstChar = minindex, + LastChar = maxindex, + Widths = pdfreference(pdfflushobject(widths)), + FontDescriptor = pdfreference(pdfflushobject(descriptor)), + Resources = resources, + ToUnicode = tounicode and pdfreference(pdfflushstreamobject(tounicode)), + } + pdfflushobject(object,parent) + if reset then + reset() + end + end + + end + +end + +-- writingmode + +local usedfonts = fonts.hashes.identifiers -- for now +local noffonts = 0 + +-- The main injector. + +-- here we need to test for sharing otherwise we reserve too many +-- objects + +local getstreamhash = fonts.handlers.otf.getstreamhash +local loadstreamdata = fonts.handlers.otf.loadstreamdata + +-- we can actually now number upwards (so not use fontid in /F) + +local objects = setmetatableindex(function(t,k) + local v + if type(k) == "number" then + local h = getstreamhash(k) + v = rawget(t,h) + if not v then + v = pdfreserveobject() + t[h] = v + end + if trace_fonts then + report_fonts("font id %i bound to hash %s and object %i",k,h,v) + end + else + -- no problem as it can be svg only + -- report_fonts("fatal error, hash %s asked but not used",k,h,v) + v = pdfreserveobject() + t[k] = v + end + return v +end) + +local n = 0 + +local names = setmetatableindex(function(t,k) + local v + if type(k) == "number" then + local h = getstreamhash(k) + v = rawget(t,h) + if not v then + n = n + 1 + v = n + t[h] = v + end + if trace_fonts then + report_fonts("font id %i bound to hash %s and name %i",k,h,n) + end + end + t[k] = v + return v +end) + +function lpdf.flushfonts() + + local mainfonts = { } + + statistics.starttiming(objects) + + for fontid, used in sortedhash(lpdf.usedcharacters) do + + -- for a bitmap we need a different hash unless we stick to a fixed high + -- resolution which makes much sense + + local hash = getstreamhash(fontid) + if hash then + local parent = mainfonts[hash] + if not parent then + local fontdata = usedfonts[fontid] + local rawdata = fontdata.shared and fontdata.shared.rawdata + local resources = fontdata.resources + local properties = fontdata.properties -- writingmode and type3 + local parameters = fontdata.parameters -- used in type3 + if not rawdata then + -- we have a virtual font that loaded directly ... at some point i will + -- sort this out (in readanddefine we need to do a bit more) .. the problem + -- is that we have a hybrid font then + for xfontid, xfontdata in next, fonts.hashes.identifiers do + if fontid ~= xfontid then + local xhash = getstreamhash(xfontid) + if hash == xhash then + rawdata = xfontdata.shared and xfontdata.shared.rawdata + if rawdata then + resources = xfontdata.resources + properties = xfontdata.properties + parameters = xfontdata.parameters + break + end + end + end + end + end + if rawdata then + parent = { + hash = hash, + fontdata = fontdata, + filename = resources.filename or properties.filename or "unset", + indices = { }, + rawdata = rawdata, + properties = properties, -- we assume consistency + parameters = parameters, -- we assume consistency + streams = { }, + objectnumber = objects[hash], + basefontname = subsetname(properties.psname or properties.name or "unset"), + name = names[hash], + } + mainfonts[hash] = parent + noffonts = noffonts + 1 + end + end + if parent then + local indices = parent.indices + for k in next, used do + indices[k] = true + end + end + end + end + + -- this is no not yet ok for tfm / type 1 .. we need to move the nested blobs ourside the loop + + for hash, details in sortedhash(mainfonts) do + local filename = details.filename + if next(details.indices) then + if trace_fonts then + report_fonts("embedding %a hashed as %a",filename,hash) + end + local properties = details.properties + local bitmap = properties.usedbitmap + local method = properties.method -- will be pk | pdf | svg | ... + if bitmap or method then + local format = "type3" + local writer = mainwriters[format] + if writer then + if trace_fonts then + report_fonts("using main writer %a",format) + end + writer(details) + end + else + local format = properties.format + local writer = mainwriters[format] + if not writer then + -- This will move to the tpk module where we will also deal + -- with bitmaps then. + local encoding, pfbfile, encfile = getmapentry(filename) + if trace_fonts then + report_fonts("file %a resolved to encoding %a and file %a",filename,encoding,pfbfile) + end + if encoding and pfbfile then + filename = pfbfile + format = "type1" + -- + -- another (temp) hack + local size = details.fontdata.parameters.size + local factor = details.fontdata.parameters.factor + local descriptions = { } + local characters = details.fontdata.characters + -- + local names, _, _, metadata = fonts.constructors.handlers.pfb.loadvector(pfbfile) + local reverse = table.swapped(names) + local vector = encoding.vector + local indices = details.indices + local remapped = { } + local factor = bpfactor * size / 65536 + for k, v in next, indices do + local name = vector[k] + local index = reverse[name] or 0 + local width = factor * (characters[k].width or 0) + descriptions[k] = { + width = width, + index = index, + name = name, + } + remapped[index] = true + end + details.indices = remapped + -- + details.rawdata.descriptions = descriptions + details.filename = filename + details.rawdata.metadata = { } + -- + properties.filename = filename + properties.format = format + writer = mainwriters[format] + end + end + if not writer then + local pfbfile = file.replacesuffix(filename,"pfb") + if encoding and pfbfile then + filename = pfbfile + format = "type1" + -- + -- another (temp) hack + local size = details.fontdata.parameters.size + local factor = details.fontdata.parameters.factor + local descriptions = { } + local characters = details.fontdata.characters + -- + local names, _, _, metadata = fonts.constructors.handlers.pfb.loadvector(pfbfile) + local reverse = table.swapped(names) + local vector = encoding.vector + local indices = details.indices + local remapped = { } + local factor = bpfactor * size / 65536 + for k, v in next, indices do + local name = vector[k] + local index = reverse[name] or 0 + local width = factor * (characters[k].width or 0) + descriptions[k] = { + width = width, + index = index, + name = name, + } + remapped[index] = true + end + details.indices = remapped + -- + details.rawdata.descriptions = descriptions + details.filename = filename + details.rawdata.metadata = { } + -- + properties.filename = filename + properties.format = format + writer = mainwriters[format] + end + end + if writer then + if trace_fonts then + report_fonts("using main writer %a",format) + end + -- better move this test to the writers .. cleaner + local streams = loadstreamdata(details.fontdata) + if streams and streams.fontheader and streams.names then + details.streams = streams + writer(details) + details.streams = { } + elseif trace_fonts then + -- can be ok for e.g. emoji + report_fonts("no streams in %a",filename) + end + -- free some memory + else -- if trace_fonts then + report_fonts("no %a writer for %a",format,filename) + end + end + else -- not problem for svg ... + -- report_fonts("no indices for %a",filename) + end + if trace_fonts then + report_fonts("embedded indices: % t",table.sortedkeys(details.indices)) + end + mainfonts[details.hash] = false -- done + end + + statistics.stoptiming(objects) + +end + +statistics.register("font embedding time",function() + if noffonts > 0 then + return format("%s seconds, %s fonts", statistics.elapsedtime(objects),noffonts) + end +end) + +-- this is temporary + +local done = false + +updaters.register("backend.update.pdf",function() + if not done then + function pdf.getfontobjnum (k) return objects[k] end + function pdf.getfontname (k) return names [k] end + function pdf.includechar () end -- maybe, when we need it + function pdf.includefont () end -- maybe, when we need it + function pdf.includecharlist () end -- maybe, when we need it + function pdf.setomitcidset (v) includecidset = not toboolean(v) end + function pdf.setomitcharset () end -- we don't need that in lmtx + function pdf.setsuppressoptionalinfo() end -- we don't need that in lmtx + function pdf.mapfile (n) loadmapfile(n) end + function pdf.mapline (n) loadmapline(n) end + -- this will change + lpdf.registerdocumentfinalizer(lpdf.flushfonts,1,"wrapping up fonts") + done = true + end +end) diff --git a/tex/context/base/mkiv/lpdf-emb.lua b/tex/context/base/mkiv/lpdf-emb.lua deleted file mode 100644 index 0f0388af0..000000000 --- a/tex/context/base/mkiv/lpdf-emb.lua +++ /dev/null @@ -1,2225 +0,0 @@ -if not modules then modules = { } end modules ['lpdf-ini'] = { - version = 1.001, - optimize = true, - 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" -} - --- vkgoeswild: Pink Floyd - Shine on You Crazy Diamond - piano cover (around that --- time I redid the code, a reminder so to say) - --- At some point I wanted to have access to the shapes so that we could use them in --- metapost. So, after looking at the cff and ttf specifications, I decided to write --- parsers. At somepoint we needed a cff parser anyway in order to calculate the --- dimensions. Then variable fonts came around and a option was added to recreate --- streams of operators and a logical next step was to do all inclusion that way. It --- was only then that I found out that some of the juggling also happens in the the --- backend, but spread over places, so I could have saved myself some time --- deciphering the specifications. Anyway, here we go. --- --- Color fonts are a bit messy. Catching issues with older fonts will break new ones --- so I don't think that it's wise to build in too many catches (like for fonts with --- zero boundingboxes, weird dimensions, transformations that in a next version are --- fixed, etc.). Better is then to wait till something gets fixed. If a spec doesn't --- tell me how to deal with it ... I'll happily wait till it does. After all we're --- not in a hurry as these fonts are mostly meant for the web or special purposes --- with manual tweaking in desk top publishing applications. Keep in mind that Emoji --- can have funny dimensions (e.g. to be consistent within a font, so no tight ones). - --- When we have moved to lmtx I will document a bit more. Till then it's experimental --- and subjected to change. - -local next, type, unpack, rawget = next, type, unpack, rawget -local char, byte, gsub, sub, match, rep, gmatch = string.char, string.byte, string.gsub, string.sub, string.match, string.rep, string.gmatch -local formatters = string.formatters -local format = string.format -local concat, sortedhash, sort = table.concat, table.sortedhash, table.sort -local utfchar = utf.char -local random, round, max, abs, ceiling = math.random, math.round, math.max, math.abs, math.ceiling -local extract, lshift, rshift, band, bor = bit32.extract, bit32.lshift, bit32.rshift, bit32.band, bit32.bor -local idiv = number.idiv -local setmetatableindex = table.setmetatableindex - -local pdfnull = lpdf.null -local pdfdictionary = lpdf.dictionary -local pdfarray = lpdf.array -local pdfconstant = lpdf.constant -local pdfstring = lpdf.string -local pdfreference = lpdf.reference -local pdfreserveobject = lpdf.reserveobject -local pdfflushobject = lpdf.flushobject -local pdfflushstreamobject = lpdf.flushstreamobject - -local report_fonts = logs.reporter("backend","fonts") - -local trace_fonts = false -local trace_details = false - -local dimenfactors = number.dimenfactors -local bpfactor = dimenfactors.bp -local ptfactor = dimenfactors.pt - -trackers.register("backend.pdf.fonts",function(v) trace_fonts = v end) - -local readers = fonts.handlers.otf.readers -local getinfo = readers.getinfo - -local setposition = utilities.files.setposition -local readstring = utilities.files.readstring -local openfile = utilities.files.open -local closefile = utilities.files.close - - --- needs checking: signed vs unsigned - -local tocardinal1 = char - -local function tocardinal2(n) - return char(extract(n,8,8),extract(n,0,8)) -end - -local function tocardinal3(n) - return char(extract(n,16,8),extract(n,8,8),extract(n,0,8)) -end - -local function tocardinal4(n) - return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) -end - -local function tointeger2(n) - return char(extract(n,8,8),extract(n,0,8)) -end - -local function tointeger3(n) - return char(extract(n,16,8),extract(n,8,8),extract(n,0,8)) -end - -local function tointeger4(n) - return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) -end - -local function tocardinal8(n) - local l = idiv(n,0x100000000) - local r = n % 0x100000000 - return char(extract(l,24,8),extract(l,16,8),extract(l,8,8),extract(l,0,8), - extract(r,24,8),extract(r,16,8),extract(r,8,8),extract(r,0,8)) -end - --- A couple of shared helpers. - -local tounicodedictionary, widtharray, collectindices, subsetname, includecidset, forcecidset, tocidsetdictionary - -do - - -- Because we supply tounicodes ourselves we only use bfchar mappings (as in the - -- backend). In fact, we can now no longer pass the tounicodes to the frontend but - -- pick them up from the descriptions. - - local f_mapping_2 = formatters["<%02X> <%s>"] - local f_mapping_4 = formatters["<%04X> <%s>"] - - local tounicode = fonts.mappings.tounicode - -local tounicode_template = [[ -%%!PS-Adobe-3.0 Resource-CMap -%%%%DocumentNeededResources: ProcSet (CIDInit) -%%%%IncludeResource: ProcSet (CIDInit) -%%%%BeginResource: CMap (TeX-%s-0) -%%%%Title: (TeX-%s-0 TeX %s 0)| -%%%%Version: 1.000 -%%%%EndComments -/CIDInit /ProcSet findresource begin - 12 dict begin - begincmap - /CIDSystemInfo - << /Registry (TeX) /Ordering (%s) /Supplement 0 >> - def - /CMapName - /TeX-Identity-%s - def - /CMapType - 2 - def - 1 begincodespacerange - <%s> <%s> - endcodespacerange - %i beginbfchar -%s - endbfchar - endcmap - CMapName currentdict /CMap defineresource pop - end -end -%%%%EndResource -%%%%EOF]] - - tounicodedictionary = function(details,indices,maxindex,name,wide) - local mapping = { } - local length = 0 - if maxindex > 0 then - local f_mapping = wide and f_mapping_4 or f_mapping_2 - for index=1,maxindex do - local data = indices[index] - if data then - length = length + 1 - local unicode = data.unicode - if unicode then - unicode = tounicode(unicode) - else - unicode = "FFFD" - end - mapping[length] = f_mapping(index,unicode) - end - end - end - local name = gsub(name,"%+","-") -- like luatex does - local first = wide and "0000" or "00" - local last = wide and "FFFF" or "FF" - local blob = format(tounicode_template,name,name,name,name,name,first,last,length,concat(mapping,"\n")) - return blob - end - - widtharray = function(details,indices,maxindex,units) - local widths = pdfarray() - local length = 0 - local factor = 10000 / units - if maxindex > 0 then - local lastindex = -1 - local sublist = nil - for index=1,maxindex do - local data = indices[index] - if data then - local width = data.width -- hm, is inaccurate for cff, so take from elsewhere - if width then - -- width = round(width * 10000 / units) / 10 - width = round(width * factor) / 10 - else - width = 0 - end - if index == lastindex + 1 then - sublist[#sublist+1] = width - else - if sublist then - length = length + 1 - widths[length] = sublist - end - sublist = pdfarray { width } - length = length + 1 - widths[length] = index - end - lastindex = index - end - end - length = length + 1 - widths[length] = sublist - end - return widths - end - - collectindices = function(descriptions,indices) - local minindex = 0xFFFF - local maxindex = 0 - local reverse = { } - -- todo: already at definition time trigger copying streams - -- and add extra indices ... first i need a good example of - -- a clash - -- for unicode, data in next, descriptions do - -- local i = data.index or unicode - -- if reverse[i] then - -- print("CLASH") - -- else - -- reverse[i] = data - -- end - -- end - for unicode, data in next, descriptions do - reverse[data.index or unicode] = data - end - for index in next, indices do - if index > maxindex then - maxindex = index - end - if index < minindex then - minindex = index - end - indices[index] = reverse[index] - end - if minindex > maxindex then - minindex = maxindex - end - return indices, minindex, maxindex - end - - includecidset = false - forcecidset = false -- for private testing only - - directives.register("backend.pdf.forcecidset",function(v) - forcecidset = v - end) - - tocidsetdictionary = function(indices,min,max) - if includecidset or forcecidset then - local b = { } - local m = idiv(max+7,8) - for i=0,max do - b[i] = 0 - end - b[0] = bor(b[0],lshift(1,7)) -- force notdef into the file - for i=min,max do - if indices[i] then - local bi = idiv(i,8) - local ni = i % 8 - b[bi] = bor(b[bi],lshift(1,7-ni)) - end - end - b = char(unpack(b,0,#b)) - return pdfreference(pdfflushstreamobject(b)) - end - end - - -- Actually we can use the same as we only embed once. - - -- subsetname = function(name) - -- return "CONTEXT" .. name - -- end - - local prefixes = { } -- todo: set fixed one - - subsetname = function(name) - local prefix - while true do - prefix = utfchar(random(65,90),random(65,90),random(65,90),random(65,90),random(65,90),random(65,90)) - if not prefixes[prefix] then - prefixes[prefix] = true - break - end - end - return prefix .. "+" .. name - end - -end - --- Map file mess. - -local loadmapfile, loadmapline, getmapentry do - - -- We only need to pick up the filename and optionally the enc file - -- as we only use them for old school virtual math fonts. We might as - -- we drop this completely. - - local find, match, splitlines = string.find, string.match, string.splitlines - - - local mappings = { } - - loadmapline = function(n) - if trace_fonts then - report_fonts("mapline: %s",n) - end - local name, fullname, encfile, pfbfile = match(n,"(%S+)%s+(%S+).-<(.-%.enc).-<(.-%.pfb)") - if name then - mappings[name] = { fullname, encfile, pfbfile } - end - end - - loadmapfile = function(n) - local okay, data = resolvers.loadbinfile(n,"map") - if okay and data then - data = splitlines(data) - for i=1,#data do - local d = data[i] - if d ~= "" and not find(d,"^[#%%]") then - loadmapline(d) - end - end - end - end - - getmapentry = function(n) - local n = file.nameonly(n) - local m = mappings[n] - if m then - local encfile = m[2] - local encoding = fonts.encodings.load(encfile) - if not encoding then - return - end - local pfbfile = resolvers.findfile(m[3],"pfb") - if not pfbfile or pfbfile == "" then - return - end - return encoding, pfbfile, encfile - end - end - - lpdf.getmapentry = getmapentry - -end - --- The three writers: opentype, truetype and type1. - -local mainwriters = { } - -do - - -- advh = os2.ascender - os2.descender - -- tsb = default_advh - os2.ascender - - -- truetype has the following tables: - - -- head : mandate - -- hhea : mandate - -- vhea : mandate - -- hmtx : mandate - -- maxp : mandate - -- glyf : mandate - -- loca : mandate - -- - -- cvt : if needed (but we flatten) - -- fpgm : if needed (but we flatten) - -- prep : if needed (but we flatten) - -- PCLT : if needed (but we flatten) - -- - -- name : not needed for T2: backend does that - -- post : not needed for T2: backend does that - -- OS/2 : not needed for T2: backend does that - -- cmap : not needed for T2: backend does that - - local streams = utilities.streams - local openstring = streams.openstring - local readcardinal2 = streams.readcardinal2 - ----- readcardinal4 = streams.readcardinal4 - - local otfreaders = fonts.handlers.otf.readers - - local function readcardinal4(f) -- this needs to be sorted out - local a = readcardinal2(f) - local b = readcardinal2(f) - if a and b then - return a * 0x10000 + b - end - end - - -- -- -- - - local tablereaders = { } - local tablewriters = { } - local tablecreators = { } - local tableloaders = { } - - local openfontfile, closefontfile, makefontfile, makemetadata do - - local details = { - details = true, - platformnames = true, - platformextras = true, - } - - -- .022 sec on luatex manual, neglectable: - - -- local function checksum(data) - -- local s = openstring(data) - -- local n = 0 - -- local d = #data - -- while true do - -- local c = readcardinal4(s) - -- if c then - -- n = (n + c) % 0x100000000 - -- else - -- break - -- end - -- end - -- return n - -- end - - local function checksum(data) - local s = openstring(data) - local n = 0 - local d = #data - while true do - local a = readcardinal2(s) - local b = readcardinal2(s) - if b then - n = (n + a * 0x10000 + b) % 0x100000000 - else - break - end - end - return n - end - - openfontfile = function(details) - return { - offset = 0, - order = { }, - used = { }, - details = details, - streams = details.streams, - } - end - - closefontfile = function(fontfile) - for k, v in next, fontfile do - fontfile[k] = nil -- so it can be collected asap - end - end - - local metakeys = { - "uniqueid", "version", - "copyright", "license", "licenseurl", - "manufacturer", "vendorurl", - "family", "subfamily", - "typographicfamily", "typographicsubfamily", - "fullname", "postscriptname", - } - - local template = [[ - - - - - -%s - - - - -]] - - makemetadata = function(fontfile) - local names = fontfile.streams.names - local list = { } - local f_name = formatters["%s"] - for i=1,#metakeys do - local m = metakeys[i] - local n = names[m] - if n then - list[#list+1] = f_name(m,n,m) - end - end - return format(template,concat(list,"\n")) - end - - makefontfile = function(fontfile) - local order = fontfile.order - local used = fontfile.used - local count = 0 - for i=1,#order do - local tag = order[i] - local data = fontfile[tag] - if data and #data > 0 then - count = count + 1 - else - fontfile[tag] = false - end - end - local offset = 12 + (count * 16) - local headof = 0 - local list = { - "" -- placeholder - } - local i = 1 - local k = 0 - while i <= count do - i = lshift(i,1) - k = k + 1 - end - local searchrange = lshift(i,3) - local entryselector = k - 1 - local rangeshift = lshift(count,4) - lshift(i,3) - local index = { - tocardinal4(0x00010000), -- tables.version - tocardinal2(count), - tocardinal2(searchrange), - tocardinal2(entryselector), - tocardinal2(rangeshift), - } - -- - local ni = #index - local nl = #list - for i=1,#order do - local tag = order[i] - local data = fontfile[tag] - if data then - local csum = checksum(data) - local dlength = #data - local length = idiv(dlength+3,4) * 4 - local padding = length - dlength - nl = nl + 1 ; list[nl] = data - for i=1,padding do - nl = nl + 1 ; list[nl] = "\0" - end - if #tag == 3 then - tag = tag .. " " - end - ni = ni + 1 ; index[ni] = tag -- must be 4 chars - ni = ni + 1 ; index[ni] = tocardinal4(csum) - ni = ni + 1 ; index[ni] = tocardinal4(offset) - ni = ni + 1 ; index[ni] = tocardinal4(dlength) - used[i] = offset -- not used - if tag == "head" then - headof = offset - end - offset = offset + length - end - end - list[1] = concat(index) - local off = #list[1] + headof + 1 + 8 - list = concat(list) - local csum = (0xB1B0AFBA - checksum(list)) % 0x100000000 - list = sub(list,1,off-1) .. tocardinal4(csum) .. sub(list,off+4,#list) - return list - end - - local function register(fontfile,name) - local u = fontfile.used - local o = fontfile.order - if not u[name] then - o[#o+1] = name - u[name] = true - end - end - - local function create(fontfile,name) - local t = { } - fontfile[name] = t - return t - end - - local function write(fontfile,name) - local t = fontfile[name] - if not t then - return - end - register(fontfile,name) - if type(t) == "table" then - if t[0] then - fontfile[name] = concat(t,"",0,#t) - elseif #t > 0 then - fontfile[name] = concat(t) - else - fontfile[name] = false - end - end - end - - tablewriters.head = function(fontfile) - register(fontfile,"head") - local t = fontfile.streams.fontheader - fontfile.head = concat { - tocardinal4(t.version), - tocardinal4(t.fontversionnumber), - tocardinal4(t.checksum), - tocardinal4(t.magic), - tocardinal2(t.flags), - tocardinal2(t.units), - tocardinal8(t.created), - tocardinal8(t.modified), - tocardinal2(t.xmin), - tocardinal2(t.ymin), - tocardinal2(t.xmax), - tocardinal2(t.ymax), - tocardinal2(t.macstyle), - tocardinal2(t.smallpixels), - tocardinal2(t.directionhint), - tocardinal2(t.indextolocformat), - tocardinal2(t.glyphformat), - } - end - - tablewriters.hhea = function(fontfile) - register(fontfile,"hhea") - local t = fontfile.streams.horizontalheader - local n = t and fontfile.nofglyphs or 0 - fontfile.hhea = concat { - tocardinal4(t.version), - tocardinal2(t.ascender), - tocardinal2(t.descender), - tocardinal2(t.linegap), - tocardinal2(t.maxadvancewidth), - tocardinal2(t.minleftsidebearing), - tocardinal2(t.minrightsidebearing), - tocardinal2(t.maxextent), - tocardinal2(t.caretsloperise), - tocardinal2(t.caretsloperun), - tocardinal2(t.caretoffset), - tocardinal2(t.reserved_1), - tocardinal2(t.reserved_2), - tocardinal2(t.reserved_3), - tocardinal2(t.reserved_4), - tocardinal2(t.metricdataformat), - tocardinal2(n) -- t.nofmetrics - } - end - - tablewriters.vhea = function(fontfile) - local t = fontfile.streams.verticalheader - local n = t and fontfile.nofglyphs or 0 - register(fontfile,"vhea") - fontfile.vhea = concat { - tocardinal4(t.version), - tocardinal2(t.ascender), - tocardinal2(t.descender), - tocardinal2(t.linegap), - tocardinal2(t.maxadvanceheight), - tocardinal2(t.mintopsidebearing), - tocardinal2(t.minbottomsidebearing), - tocardinal2(t.maxextent), - tocardinal2(t.caretsloperise), - tocardinal2(t.caretsloperun), - tocardinal2(t.caretoffset), - tocardinal2(t.reserved_1), - tocardinal2(t.reserved_2), - tocardinal2(t.reserved_3), - tocardinal2(t.reserved_4), - tocardinal2(t.metricdataformat), - tocardinal2(n) -- t.nofmetrics - } - end - - tablewriters.maxp = function(fontfile) - register(fontfile,"maxp") - local t = fontfile.streams.maximumprofile - local n = fontfile.nofglyphs - -- if fontfile.streams.cffinfo then - -- error - -- end - fontfile.maxp = concat { - tocardinal4(0x00010000), - tocardinal2(n), - tocardinal2(t.points), - tocardinal2(t.contours), - tocardinal2(t.compositepoints), - tocardinal2(t.compositecontours), - tocardinal2(t.zones), - tocardinal2(t.twilightpoints), - tocardinal2(t.storage), - tocardinal2(t.functiondefs), - tocardinal2(t.instructiondefs), - tocardinal2(t.stackelements), - tocardinal2(t.sizeofinstructions), - tocardinal2(t.componentelements), - tocardinal2(t.componentdepth), - } - end - - tablecreators.loca = function(fontfile) return create(fontfile,"loca") end - tablewriters .loca = function(fontfile) return write (fontfile,"loca") end - - tablecreators.glyf = function(fontfile) return create(fontfile,"glyf") end - tablewriters .glyf = function(fontfile) return write (fontfile,"glyf") end - - tablecreators.hmtx = function(fontfile) return create(fontfile,"hmtx") end - tablewriters .hmtx = function(fontfile) return write (fontfile,"hmtx") end - - tablecreators.vmtx = function(fontfile) return create(fontfile,"vmtx") end - tablewriters .vmtx = function(fontfile) return write (fontfile,"vmtx") end - - tableloaders .cmap = function(fontfile) return read (fontfile,"cmap") end - tablewriters .cmap = function(fontfile) return write (fontfile,"cmap") end - - tableloaders .name = function(fontfile) return read (fontfile,"name") end - tablewriters .name = function(fontfile) return write (fontfile,"name") end - - tableloaders .post = function(fontfile) return read (fontfile,"post") end - tablewriters .post = function(fontfile) return write (fontfile,"post") end - - end - - mainwriters["truetype"] = function(details) - -- - local fontfile = openfontfile(details) - local basefontname = details.basefontname - local streams = details.streams - local blobs = streams.streams - local fontheader = streams.fontheader - local horizontalheader = streams.horizontalheader - local verticalheader = streams.verticalheader - local maximumprofile = streams.maximumprofile - local names = streams.names - local descriptions = details.rawdata.descriptions - local metadata = details.rawdata.metadata - local indices = details.indices - local metabbox = { fontheader.xmin, fontheader.ymin, fontheader.xmax, fontheader.ymax } - local indices, - minindex, - maxindex = collectindices(descriptions,indices) - local glyphstreams = tablecreators.glyf(fontfile) - local locations = tablecreators.loca(fontfile) - local horizontals = tablecreators.hmtx(fontfile) - local verticals = tablecreators.vmtx(fontfile) - -- - local zero2 = tocardinal2(0) - local zero4 = tocardinal4(0) - -- - local horizontal = horizontalheader.nofmetrics > 0 - local vertical = verticalheader.nofmetrics > 0 - -- - local streamoffset = 0 - local lastoffset = zero4 - local g, h, v = 0, 0, 0 - -- - -- todo: locate notdef - -- - if minindex > 0 then - local blob = blobs[0] - if blob and #blob > 0 then - locations[0] = lastoffset - g = g + 1 ; glyphstreams[g] = blob - h = h + 1 ; horizontals [h] = zero4 - if vertical then - v = v + 1 ; verticals[v] = zero4 - end - streamoffset = streamoffset + #blob - lastoffset = tocardinal4(streamoffset) - else - report_fonts("missing .notdef in font %a",basefontname) - end - -- todo: use a rep for h/v - for index=1,minindex-1 do - locations[index] = lastoffset - h = h + 1 ; horizontals[h] = zero4 - if vertical then - v = v + 1 ; verticals[v] = zero4 - end - end - end - for index=minindex,maxindex do - locations[index] = lastoffset - local data = indices[index] - if data then - local blob = blobs[index] -- we assume padding - if blob and #blob > 0 then - g = g + 1 ; glyphstreams[g] = blob - h = h + 1 ; horizontals [h] = tocardinal2(data.width or 0) - h = h + 1 ; horizontals [h] = tocardinal2(data.boundingbox[1]) - if vertical then - v = v + 1 ; verticals[v] = tocardinal2(data.height or 0) - v = v + 1 ; verticals[v] = tocardinal2(data.boundingbox[3]) - end - streamoffset = streamoffset + #blob - lastoffset = tocardinal4(streamoffset) - else - h = h + 1 ; horizontals[h] = zero4 - if vertical then - v = v + 1 ; verticals[v] = zero4 - end - report_fonts("missing blob for index %i in font %a",index,basefontname) - end - else - h = h + 1 ; horizontals[h] = zero4 - if vertical then - v = v + 1 ; verticals[v] = zero4 - end - end - end - locations[maxindex+1] = lastoffset -- cf spec - -- - local nofglyphs = maxindex + 1 -- include zero - -- - fontheader.checksum = 0 - fontheader.indextolocformat = 1 - maximumprofile.nofglyphs = nofglyphs - -- - fontfile.format = "tff" - fontfile.basefontname = basefontname - fontfile.nofglyphs = nofglyphs - -- - tablewriters.head(fontfile) - tablewriters.hhea(fontfile) - if vertical then - tablewriters.vhea(fontfile) - end - tablewriters.maxp(fontfile) - - tablewriters.loca(fontfile) - tablewriters.glyf(fontfile) - - tablewriters.hmtx(fontfile) - if vertical then - tablewriters.vmtx(fontfile) - end - -- - local fontdata = makefontfile(fontfile) - local fontmeta = makemetadata(fontfile) - -- - fontfile = closefontfile(fontfile) - -- - local units = metadata.units - local basefont = pdfconstant(basefontname) - local widths = widtharray(details,indices,maxindex,units) - local object = details.objectnumber - local tounicode = tounicodedictionary(details,indices,maxindex,basefontname,true) - local tocidset = tocidsetdictionary(indices,minindex,maxindex) - local metabbox = metadata.boundingbox or { 0, 0, 0, 0 } - local fontbbox = pdfarray { unpack(metabbox) } - local ascender = metadata.ascender - local descender = metadata.descender - local capheight = metadata.capheight or fontbbox[4] - local stemv = metadata.weightclass - local italicangle = metadata.italicangle - local xheight = metadata.xheight or fontbbox[4] - -- - if stemv then - stemv = (stemv/65)^2 + 50 - end - -- - local function scale(n) - if n then - return round((n) * 10000 / units) / 10 - else - return 0 - end - end - -- - local reserved = pdfreserveobject() - local child = pdfdictionary { - Type = pdfconstant("Font"), - Subtype = pdfconstant("CIDFontType2"), - BaseFont = basefont, - FontDescriptor = pdfreference(reserved), - W = pdfreference(pdfflushobject(widths)), - CIDToGIDMap = pdfconstant("Identity"), - CIDSystemInfo = pdfdictionary { - Registry = pdfstring("Adobe"), - Ordering = pdfstring("Identity"), - Supplement = 0, - } - } - local descendants = pdfarray { - pdfreference(pdfflushobject(child)), - } - local descriptor = pdfdictionary { - Type = pdfconstant("FontDescriptor"), - FontName = basefont, - Flags = 4, - FontBBox = fontbbox, - Ascent = scale(ascender), - Descent = scale(descender), - ItalicAngle = round(italicangle or 0), - CapHeight = scale(capheight), - StemV = scale(stemv), - XHeight = scale(xheight), - FontFile2 = pdfreference(pdfflushstreamobject(fontdata)), - CIDSet = tocidset, - Metadata = fontmeta and pdfreference(pdfflushstreamobject(fontmeta)) or nil, - } - local parent = pdfdictionary { - Type = pdfconstant("Font"), - Subtype = pdfconstant("Type0"), - Encoding = pdfconstant(details.properties.writingmode == "vertical" and "Identity-V" or "Identity-H"), - BaseFont = basefont, - DescendantFonts = descendants, - ToUnicode = pdfreference(pdfflushstreamobject(tounicode)), - } - pdfflushobject(reserved,descriptor) - pdfflushobject(object,parent) - -- - -- if trace_details then - -- local name = "temp.ttf" - -- report_fonts("saving %a",name) - -- io.savedata(name,fontdata) - -- inspect(fonts.handlers.otf.readers.loadfont(name)) - -- end - -- - end - - do - -- todo : cff2 - - local details = { - details = true, - platformnames = true, - platformextras = true, - } - - tablecreators.cff = function(fontfile) - fontfile.charstrings = { } - fontfile.charmappings = { } - fontfile.cffstrings = { } - fontfile.cffhash = { } - return fontfile.charstrings , fontfile.charmappings - end - - local todictnumber, todictreal, todictinteger, todictoffset do - - local maxnum = 0x7FFFFFFF - local minnum = - 0x7FFFFFFF - 1 - local epsilon = 1.0e-5 - - local int2tag = "\28" - local int4tag = "\29" - local realtag = "\30" - - todictinteger = function(n) - if not n then - return char(band(139,0xFF)) - elseif n >= -107 and n <= 107 then - return char(band(n + 139,0xFF)) - elseif n >= 108 and n <= 1131 then - n = 0xF700 + n - 108 - return char(band(rshift(n,8),0xFF),band(n,0xFF)) - elseif n >= -1131 and n <= -108 then - n = 0xFB00 - n - 108 - return char(band(rshift(n,8),0xFF),band(n,0xFF)) - elseif n >= -32768 and n <= 32767 then - -- return int2tag .. tointeger2(n) - return char(28,extract(n,8,8),extract(n,0,8)) - else - -- return int4tag .. tointeger4(n) - return char(29,extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) - end - end - - -- -- not called that often - -- - -- local encoder = readers.cffencoder - -- - -- todictinteger = function(n) - -- if not n then - -- return encoder[0] - -- elseif n >= -1131 and n <= 1131 then - -- return encoder[n] - -- elseif n >= -32768 and n <= 32767 then - -- -- return int2tag .. tointeger2(n) - -- return char(28,extract(n,8,8),extract(n,0,8)) - -- else - -- -- return int4tag .. tointeger4(n) - -- return char(29,extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) - -- end - -- end - - todictoffset = function(n) - return int4tag .. tointeger4(n) - end - - local e = false - local z = byte("0") - local dp = 10 - local ep = 11 - local em = 12 - local mn = 14 - local es = 15 - - local fg = formatters["%g"] - - todictreal = function(v) - local s = fg(v) - local t = { [0] = realtag } - local n = 0 - for s in gmatch(s,".") do - if s == "e" or s == "E" then - e = true - elseif s == "+" then - -- skip - elseif s == "-" then - n = n + 1 - if e then - t[n] = em - e = false - else - t[n] = mn - end - else - if e then - n = n + 1 - t[n] = ep - e = false - end - n = n + 1 - if s == "." then - t[n] = dp - else - t[n] = byte(s) - z - end - end - end - n = n + 1 - t[n] = es - if (n % 2) ~= 0 then - n = n + 1 - t[n] = es - end - local j = 0 - for i=1,n,2 do - j = j + 1 - t[j] = char(t[i]*0x10+t[i+1]) - end - t = concat(t,"",0,j) - return t - end - - todictnumber = function(n) - if not n or n == 0 then - return todictinteger(0) - elseif (n > maxnum or n < minnum or (abs(n - round(n)) > epsilon)) then - return todictreal(n) - else - return todictinteger(n) - end - end - - end - - local todictkey = char - - local function todictstring(fontfile,value) - if not value then - value = "" - end - local s = fontfile.cffstrings - local h = fontfile.cffhash - local n = h[value] - if not n then - n = #s + 1 - s[n] = value - h[value] = n - end - return todictinteger(390+n) - end - - local function todictboolean(b) - return todictinteger(b and 1 or 0) - end - - local function todictdeltas(t) - local r = { } - for i=1,#t do - r[i] = todictnumber(t[i]-(t[i-1] or 0)) - end - return concat(r) - end - - local function todictarray(t) - local r = { } - for i=1,#t do - r[i] = todictnumber(t[i]) - end - return concat(r) - end - - local function writestring(target,source,offset,what) - target[#target+1] = source - -- report_fonts("string : %-11s %06i # %05i",what,offset,#source) - return offset + #source - end - - local function writetable(target,source,offset,what) - source = concat(source) - target[#target+1] = source - -- report_fonts("table : %-11s %06i # %05i",what,offset,#source) - return offset + #source - end - - local function writeindex(target,source,offset,what) - local n = #source - local t = #target - t = t + 1 ; target[t] = tocardinal2(n) - if n > 0 then - local data = concat(source) - local size = #data -- assume the worst - local offsetsize, tocardinal - if size < 0xFF then - offsetsize, tocardinal = 1, tocardinal1 - elseif size < 0xFFFF then - offsetsize, tocardinal = 2, tocardinal2 - elseif size < 0xFFFFFF then - offsetsize, tocardinal = 3, tocardinal3 - elseif size < 0xFFFFFFFF then - offsetsize, tocardinal = 4, tocardinal4 - end - -- report_fonts("index : %-11s %06i # %05i (%i entries with offset size %i)",what,offset,#data,n,offsetsize) - offset = offset + 2 + 1 + (n + 1) * offsetsize + size - -- bytes per offset - t = t + 1 ; target[t] = tocardinal1(offsetsize) - -- list of offsets (one larger for length calculation) - local offset = 1 -- mandate - t = t + 1 ; target[t] = tocardinal(offset) - for i=1,n do - offset = offset + #source[i] - t = t + 1 ; target[t] = tocardinal(offset) - end - t = t + 1 ; target[t] = data - else - -- report_fonts("index : %-11s %06i # %05i (no entries)",what,offset,0) - offset = offset + 2 - end - -- print("offset",offset,#concat(target)) - return offset - end - - tablewriters.cff = function(fontfile) - -- - local streams = fontfile.streams - local cffinfo = streams.cffinfo or { } - local names = streams.names or { } - local fontheader = streams.fontheader or { } - local basefontname = fontfile.basefontname - -- - local offset = 0 - local dictof = 0 - local target = { } - -- - local charstrings = fontfile.charstrings - local nofglyphs = #charstrings + 1 - local fontmatrix = { 0.001, 0, 0, 0.001, 0, 0 } -- todo - local fontbbox = fontfile.fontbbox - local defaultwidth = cffinfo.defaultwidth or 0 - local nominalwidth = cffinfo.nominalwidth or 0 - local bluevalues = cffinfo.bluevalues - local otherblues = cffinfo.otherblues - local familyblues = cffinfo.familyblues - local familyotherblues = cffinfo.familyotherblues - local bluescale = cffinfo.bluescale - local blueshift = cffinfo.blueshift - local bluefuzz = cffinfo.bluefuzz - local stdhw = cffinfo.stdhw - local stdvw = cffinfo.stdvw - -- - if defaultwidth == 0 then defaultwidth = nil end - if nomimalwidth == 0 then nominalwidth = nil end - if bluevalues then bluevalues = todictarray(bluevalues) end - if otherblues then otherblues = todictarray(otherblues) end - if familyblues then familyblues = todictarray(familyblues) end - if familyotherblues then familyotherblues = todictarray(familyotherblues) end - if bluescale then bluescale = todictnumber(bluescale) end - if blueshift then blueshift = todictnumber(blueshift) end - if bluefuzz then bluefuzz = todictnumber(bluefuzz) end - if stdhw then stdhw = todictdeltas(stdhw) end - if stdvw then stdvw = todictdeltas(stdvw) end - -- - local fontversion = todictstring(fontfile,fontheader.fontversion or "uknown version") - local familyname = todictstring(fontfile,cffinfo.familyname or names.family or basefontname) - local fullname = todictstring(fontfile,cffinfo.fullname or basefontname) - local weight = todictstring(fontfile,cffinfo.weight or "Normal") - local fontbbox = todictarray(fontbbox) - local strokewidth = todictnumber(cffinfo.strokewidth) - local monospaced = todictboolean(cffinfo.monospaced) - local italicangle = todictnumber(cffinfo.italicangle) - local underlineposition = todictnumber(cffinfo.underlineposition) - local underlinethickness = todictnumber(cffinfo.underlinethickness) - local charstringtype = todictnumber(2) - local fontmatrix = todictarray(fontmatrix) - local ros = todictstring(fontfile,"Adobe") -- registry - .. todictstring(fontfile,"Identity") -- identity - .. todictnumber(0) -- supplement - local cidcount = todictnumber(fontfile.nofglyphs) - local fontname = todictstring(fontfile,basefontname) - local fdarrayoffset = todictoffset(0) - local fdselectoffset = todictoffset(0) - local charstringoffset = todictoffset(0) - local charsetoffset = todictoffset(0) - local privateoffset = todictoffset(0) - -- - local defaultwidthx = todictnumber(defaultwidth) - local nominalwidthx = todictnumber(nominalwidth) - local private = "" - .. (defaultwidthx and (defaultwidthx .. todictkey(20)) or "") - .. (nominalwidthx and (nominalwidthx .. todictkey(21)) or "") - .. (bluevalues and (bluevalues .. todictkey(6)) or "") - .. (otherblues and (otherblues .. todictkey(7)) or "") - .. (familyblues and (familyblues .. todictkey(8)) or "") - .. (familyotherblues and (familyotherblues .. todictkey(9)) or "") - .. (bluescale and (bluescale .. todictkey(12,9)) or "") - .. (blueshift and (blueshift .. todictkey(12,10)) or "") - .. (bluefuzz and (bluefuzz .. todictkey(12,11)) or "") - .. (stdhw and (stdhw .. todictkey(12,12)) or "") - .. (stdvw and (stdvw .. todictkey(12,13)) or "") - local privatesize = todictnumber(#private) - local privatespec = privatesize .. privateoffset - -- - -- header (fixed @ 1) - -- - local header = - tocardinal1(1) -- major - .. tocardinal1(0) -- minor - .. tocardinal1(4) -- header size - .. tocardinal1(4) -- offset size - -- - offset = writestring(target,header,offset,"header") - -- - -- name index (fixed @ 2) (has to be sorted) - -- - local names = { - basefontname, - } - -- - offset = writeindex(target,names,offset,"names") - -- - -- topdict index (fixed @ 3) - -- - local topvars = - charstringoffset .. todictkey(17) - .. charsetoffset .. todictkey(15) - .. fdarrayoffset .. todictkey(12,36) - .. fdselectoffset .. todictkey(12,37) - .. privatespec .. todictkey(18) - -- - local topdict = { - ros .. todictkey(12,30) -- first - .. cidcount .. todictkey(12,34) - .. familyname .. todictkey( 3) - .. fullname .. todictkey( 2) - .. weight .. todictkey( 4) - .. fontbbox .. todictkey( 5) - .. monospaced .. todictkey(12, 1) - .. italicangle .. todictkey(12, 2) - .. underlineposition .. todictkey(12, 3) - .. underlinethickness .. todictkey(12, 4) - .. charstringtype .. todictkey(12, 6) - .. fontmatrix .. todictkey(12, 7) - .. strokewidth .. todictkey(12, 8) - .. topvars - } - -- - offset = writeindex(target,topdict,offset,"topdict") - dictof = #target - -- - -- string index (fixed @ 4) - -- - offset = writeindex(target,fontfile.cffstrings,offset,"strings") - -- - -- global subroutine index (fixed @ 5) - -- - offset = writeindex(target,{},offset,"globals") - -- - -- Encoding (cff1) - -- - -- offset = writeindex(target,{},offset,"encoding") - -- - -- Charsets - -- - charsetoffset = todictoffset(offset) - offset = writetable(target,fontfile.charmappings,offset,"charsets") - -- - -- fdselect - -- - local fdselect = - tocardinal1(3) -- format - .. tocardinal2(1) -- n of ranges - -- entry 1 - .. tocardinal2(0) -- first gid - .. tocardinal1(0) -- fd index - -- entry 2 --- .. tocardinal2(fontfile.sparsemax-1) -- sentinel - .. tocardinal2(fontfile.sparsemax) -- sentinel - -- - fdselectoffset = todictoffset(offset) - offset = writestring(target,fdselect,offset,"fdselect") - -- - -- charstrings - -- - charstringoffset = todictoffset(offset) - offset = writeindex(target,charstrings,offset,"charstrings") - -- - -- font dict - -- - -- offset = writeindex(target,{},offset,"fontdict") - -- - -- private - -- - privateoffset = todictoffset(offset) - privatespec = privatesize .. privateoffset - offset = writestring(target,private,offset,"private") - -- - local fdarray = { - fontname .. todictkey(12,38) - .. privatespec .. todictkey(18) - } - fdarrayoffset = todictoffset(offset) - offset = writeindex(target,fdarray,offset,"fdarray") - -- - topdict = target[dictof] - topdict = sub(topdict,1,#topdict-#topvars) - topvars = - charstringoffset .. todictkey(17) - .. charsetoffset .. todictkey(15) - .. fdarrayoffset .. todictkey(12,36) - .. fdselectoffset .. todictkey(12,37) - .. privatespec .. todictkey(18) - target[dictof] = topdict .. topvars - -- - target = concat(target) - -- if trace_details then - -- local name = "temp.cff" - -- report_fonts("saving %a",name) - -- io.savedata(name,target) - -- inspect(fonts.handlers.otf.readers.cffcheck(name)) - -- end - return target - end - - end - - -- todo: check widths (missing a decimal) - - mainwriters["opentype"] = function(details) - -- - local fontfile = openfontfile(details) - local basefontname = details.basefontname - local streams = details.streams - local blobs = streams.streams - local fontheader = streams.fontheader - local maximumprofile = streams.maximumprofile - local names = streams.names - local descriptions = details.rawdata.descriptions - local metadata = details.rawdata.metadata - local indices = details.indices - local metabbox = { fontheader.xmin, fontheader.ymin, fontheader.xmax, fontheader.ymax } - local correction = 1 - - -- (*) We share code with type1 and when we have old school tfm with - -- pfb but without descriptions we're kind of toast. - - if not descriptions or not next(descriptions) then - -- This is good enough, we only need indices and widths. - descriptions = details.fontdata.characters - -- This is a hack, we have no basepoints. - correction = details.fontdata.parameters.size / 1000 - -- And this needs checking. - correction = correction * bpfactor / ptfactor - metadata = { } - end - - -- - - local indices, - minindex, - maxindex = collectindices(descriptions,indices) - local streamoffset = 0 - local glyphstreams, - charmappings = tablecreators.cff(fontfile) - -- - local zero2 = tocardinal2(0) - local zero4 = tocardinal4(0) - -- - -- we need to locate notdef (or store its unicode someplace) - -- - local blob = blobs[0] or "\14" - local sparsemax = 1 - local lastoffset = zero4 - glyphstreams[sparsemax] = blob - charmappings[sparsemax] = tocardinal1(0) -- format 0 - streamoffset = streamoffset + #blob - lastoffset = tocardinal4(streamoffset) - if minindex == 0 then - minindex = 1 - end - for index=minindex,maxindex do - if indices[index] then - local blob = blobs[index] or "\14" - sparsemax = sparsemax + 1 - glyphstreams[sparsemax] = blob - charmappings[sparsemax] = tocardinal2(index) - streamoffset = streamoffset + #blob - lastoffset = tocardinal4(streamoffset) - end - end - -- - fontfile.nofglyphs = maxindex + 1 - fontfile.sparsemax = sparsemax - fontfile.format = "cff" - fontfile.basefontname = basefontname - fontfile.fontbbox = metabbox - -- - local fontdata = tablewriters.cff(fontfile) - local fontmeta = makemetadata(fontfile) - -- - fontfile = closefontfile(fontfile) - -- - local units = fontheader.units or metadata.units - - local basefont = pdfconstant(basefontname) - local widths = widtharray(details,indices,maxindex,units * correction) - local object = details.objectnumber - local tounicode = tounicodedictionary(details,indices,maxindex,basefontname,true) - local tocidset = tocidsetdictionary(indices,minindex,maxindex) - local fontbbox = pdfarray { unpack(metabbox) } - local ascender = metadata.ascender or 0 - local descender = metadata.descender or 0 - local capheight = metadata.capheight or fontbbox[4] - local stemv = metadata.weightclass - local italicangle = metadata.italicangle - local xheight = metadata.xheight or fontbbox[4] - if stemv then - stemv = (stemv/65)^2 + 50 - else --- stemv = 2 - end - -- - local function scale(n) - if n then - return round((n) * 10000 / units) / 10 - else - return 0 - end - end - -- - local reserved = pdfreserveobject() - local child = pdfdictionary { - Type = pdfconstant("Font"), - Subtype = pdfconstant("CIDFontType0"), - BaseFont = basefont, - FontDescriptor = pdfreference(reserved), - W = pdfreference(pdfflushobject(widths)), - CIDSystemInfo = pdfdictionary { - Registry = pdfstring("Adobe"), - Ordering = pdfstring("Identity"), - Supplement = 0, - } - } - local descendants = pdfarray { - pdfreference(pdfflushobject(child)), - } - local fontstream = pdfdictionary { - Subtype = pdfconstant("CIDFontType0C"), - } - local descriptor = pdfdictionary { - Type = pdfconstant("FontDescriptor"), - FontName = basefont, - Flags = 4, - FontBBox = fontbbox, - Ascent = scale(ascender), - Descent = scale(descender), - ItalicAngle = round(italicangle or 0), - CapHeight = scale(capheight), - StemV = scale(stemv), - XHeight = scale(xheight), - CIDSet = tocidset, - FontFile3 = pdfreference(pdfflushstreamobject(fontdata,fontstream())), - Metadata = fontmeta and pdfreference(pdfflushstreamobject(fontmeta)) or nil, - } - local parent = pdfdictionary { - Type = pdfconstant("Font"), - Subtype = pdfconstant("Type0"), - Encoding = pdfconstant(details.properties.writingmode == "vertical" and "Identity-V" or "Identity-H"), - BaseFont = basefont, - DescendantFonts = descendants, - ToUnicode = pdfreference(pdfflushstreamobject(tounicode)), - } - pdfflushobject(reserved,descriptor) - pdfflushobject(object,parent) - end - - mainwriters["type1"] = function(details) - -- We abuse the cff includer which is ok but for special cases like - -- tfm -> pfb we don't have the right descriptions and scale so this - -- is why we cheat elsewhere. Maybe I should just drop that kind of - -- support and assume afm files to be present. See (*) above. - local s = details.streams - local m = details.rawdata.metadata - if m then - local h = s.horizontalheader - local c = s.cffinfo - local n = s.names - h.ascender = m.ascender or h.ascender - h.descender = m.descender or h.descender - n.copyright = m.copyright or n.copyright - n.family = m.familyname or n.familyname - n.fullname = m.fullname or n.fullname - n.fontname = m.fontname or n.fontname - n.subfamily = m.subfamilyname or n.subfamilyname - n.version = m.version or n.version - setmetatableindex(h,m) - setmetatableindex(c,m) - setmetatableindex(n,m) - end - mainwriters["opentype"](details) - end - - do - - -- The methods might become plugins. - - local methods = { } - - local pdfimage = lpdf.epdf.image - local openpdf = pdfimage.open - local closepdf = pdfimage.close - local copypage = pdfimage.copy - - 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_xy = formatters["%.6N 0 d0 1 0 0 1 %.6N %.6N cm /%s Do"] - local f_image_c = formatters["/%s Do"] - local f_image_c_xy = formatters["%.6N 0 0 %.6N %.6N %.6N cm /%s Do"] - local f_image_w = formatters["%.6N 0 d0 %s"] - local f_image_d = formatters["%.6N 0 d0 1 0 0 1 0 %.6N cm /%s Do"] - local f_stream = formatters["%.6N 0 d0 %s"] - local f_stream_c = formatters["%.6N 0 0 0 0 0 d1 %s"] - local f_stream_d = formatters["%.6N 0 d0 1 0 0 1 0 %.6N 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. We also need to - -- make sure that we use bytes as index in the page stream as well as in the - -- tounicode vector. - - local c_notdef = nil - local r_notdef = nil - local w_notdef = nil - local fontbbox = nil - - -- pk inclusion (not really tested but not really used either) - - function methods.pk(filename) - local pkfullname = resolvers.findpk(basedfontname,resolution) - if not pkfullname or pkfullname == "" then - return - end - local readers = fonts.handlers.tfm.readers - local result = readers.loadpk(pkfullname) - local convert = readers.pktopdf - if not result or result.error then - return - end - local resolution = 600 - local widthfactor = resolution / 72 - local scalefactor = 72 / resolution / 10 - local factor = widthfactor / 65536 - local function pktopdf(glyph,data) - return convert(glyph,data,factor) -- return pdfcode, width - end - return result.glyphs, scalefactor, pktopdf, false, false - end - - -- pdf inclusion - - local used = setmetatableindex("table") - - function methods.pdf(filename,details) - local properties = details.properties - local pdfshapes = properties.indexdata[1] - local pdfdoc = openpdf(pdfshapes.filename) - 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 useddoc = used[pdfdoc] - local function pdftopdf(glyph,data) - local width = (data.width or 0) * factor - local image = useddoc[glyph] - local reference = nil - if not image then - image = embedimage(copypage(pdfdoc,glyph)) - nofglyphs = nofglyphs + 1 - local name = f_glyph(nofglyphs) - local stream = nil - if fixdepth then - local depth = data.depth or 0 - local height = data.height or 0 - if depth ~= 0 or height ~= 0 then - local d = data.dropin.descriptions[data.index] - local b = d.boundingbox - local l = b[1] - local r = b[3] - local w = r - l - local scale = w / d.width - local x = l - local y = - b[4] - b[2] - d.depth - local scale = w / (image.width * bpfactor) - stream = f_image_c_xy(scale,scale,x,y,name) - else - stream = f_image_c(name) - end - else - stream = f_image_c(name) - end - useddoc[glyph] = image - image.embedded_name = name - image.embedded_stream = stream - image.embedded_reference = pdfreference(image.objnum) - end - xforms[image.embedded_name] = image.embedded_reference - return f_image_w(width,image.embedded_stream), width - end - local function closepdf() - -- closepdf(pdfdoc) - end - local function getresources() - return pdfdictionary { XObject = xforms } - end - return pdfshapes, 1/units, pdftopdf, closepdf, getresources - end - end - - -- mps inclusion - - local decompress = gzip.decompress - local metapost = metapost - local simplemprun = metapost.simple - local setparameterset = metapost.setparameterset - - function methods.mps(filename,details) - local properties = details.properties - local parameters = details.parameters - local mpshapes = properties.indexdata[1] -- indexdata will change - if mpshapes then - local scale = 10 * parameters.size/parameters.designsize - local units = mpshapes.units or parameters.units - local factor = units * bpfactor / scale - local fixdepth = mpshapes.fixdepth - local usecolor = mpshapes.usecolor - local specification = mpshapes.specification - local shapedefinitions = mpshapes.shapes - local instance = mpshapes.instance - -- - simplemprun(instance,"begingroup;",true,true) - setparameterset("mpsfont",specification) - if shapedefinitions then - local preamble = shapedefinitions.parameters.preamble - if preamble then - simplemprun(instance,preamble,true,true) - end - end - -- - local function mpstopdf(mp,data) - local width = data.width - if decompress then - mp = decompress(mp) - end - local pdf = simplemprun(instance,mp,true) -- can be sped up, minifun - local width = width * factor - if usecolor then - return f_stream_c(width,pdf), width - elseif 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 resetmps() - setparameterset("mpsfont") - simplemprun(instance,"endgroup;",true,true) - end - -- - local function getresources() - return lpdf.collectedresources { - serialize = false, - } - end - -- - return mpshapes, 1/units, mpstopdf, resetmps, getresources - end - end - - -- png inclusion - - -- With d1 the image mask is used when given and obeys color. So it is needed for pure bw - -- bitmap fonts, so here we really need d0. - -- - -- Acrobat X pro only seems to see the image mask but other viewers are doing it ok. Acrobat - -- reader crashes. We really need to add a notdef! - - local files = utilities.files - local openfile = files.open - local closefile = files.close - local setposition = files.setposition - local readstring = files.readstring - - function methods.png(filename,details) - local properties = details.properties - local pngshapes = properties.indexdata[1] - if pngshapes then - local parameters = details.parameters - local png = properties.png - local hash = png.hash - local xforms = pdfdictionary() - local nofglyphs = 0 - local scale = 10 * parameters.size/parameters.designsize - local factor = bpfactor / scale - -- local units = parameters.units -- / 1000 - local units = 1000 - local filehandle = openfile(details.filename,true) - local function pngtopdf(glyph,data) - -- local info = graphics.identifiers.png(glyph.data,"string") - local offset = glyph.o - local size = glyph.s - local pdfdata = nil - if offset and size then - setposition(filehandle,offset) - local blob = readstring(filehandle,size) - local info = graphics.identifiers.png(blob,"string") - info.enforcecmyk = pngshapes.enforcecmyk - local image = lpdf.injectors.png(info,"string") - local width = (data.width or 0) * factor - if image then - embedimage(image) - nofglyphs = nofglyphs + 1 - local xoffset = (glyph.x or 0) / units - local yoffset = (glyph.y or 0) / units - local name = f_glyph(nofglyphs) - xforms[name] = pdfreference(image.objnum) - pdfdata = f_image_xy(width,xoffset,yoffset,name) - end - end - return pdfdata or f_stream(width), width - end - local function closepng() - if filehandle then - closefile(filehandle) - end - pngshapes = nil - end - local function getresources() - return pdfdictionary { XObject = xforms } - end - return pngshapes, 1, pngtopdf, closepng, getresources - end - end - - function methods.color(filename,details) - local colrshapes = details.properties.indexdata[1] - local colrvalues = details.properties.indexdata[2] - local usedfonts = { } - local function colrtopdf(description,data) - -- descriptions by index - local colorlist = description.colors - if colorlist then - local dropdata = data.dropin - local dropid = dropdata.properties.id - local dropunits = dropdata.parameters.units -- shared - local descriptions = dropdata.descriptions - usedfonts[dropid] = dropid - local w = description.width or 0 - local s = #colorlist - local l = nil - 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 - if v and l ~= v then - n = n + 1 ; t[n] = v - l = v - end - local e = descriptions[entry.slot] - if e then - n = n + 1 ; t[n] = f_char(dropid,e.index) - end - end - return concat(t," "), w / dropunits - end - end - local function getresources() - return lpdf.collectedresources { - serialize = false, - fonts = usedfonts, - fontprefix = "V", - } - end - return colrshapes, 1, colrtopdf, false, getresources - end - - mainwriters["type3"] = function(details) - local properties = details.properties - local basefontname = details.basefontname or properties.name - local askedmethod = properties.method or "pk" - local method = methods[askedmethod] or methods.pk - if not method then - return - end - local glyphs, scalefactor, glyphtopdf, reset, getresources = method(basedfontname,details) - if not glyphs then - return - end - local parameters = details.parameters - local object = details.objectnumber - local factor = parameters.factor -- normally 1 - local fontmatrix = pdfarray { scalefactor, 0, 0, scalefactor, 0, 0 } - local indices, - minindex, - maxindex = collectindices(details.fontdata.characters,details.indices) - local widths = pdfarray() - local differences = pdfarray() - local charprocs = pdfdictionary() - local basefont = pdfconstant(basefontname) - local d = 0 - local w = 0 - local forcenotdef = minindex > 0 - local lastindex = -0xFF - if forcenotdef then - widths[0] = 0 - minindex = 0 - lastindex = 0 - d = 2 - if not c_notdef then - w_notdef = 0 - c_notdef = pdfconstant(".notdef") - r_notdef = pdfreference(pdfflushstreamobject("0 0 d0")) - end - differences[1] = w_notdef - differences[2] = c_notdef - charprocs[".notdef"] = r_notdef - end - - 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] - if glyph then - local stream, width = glyphtopdf(glyph,data) - if stream then - if index - 1 ~= lastindex then - d = d + 1 differences[d] = index - end - lastindex = index - d = d + 1 differences[d] = pdfconstant(name) - charprocs[name] = pdfreference(pdfflushstreamobject(stream)) - widths[index-minindex+1] = width - end - else - report_fonts("missing glyph %i in type3 font %a",index,basefontname) - end - end - if not fontbbox then - -- The specification permits zero values and these are actually also more - -- robust as then there are no assumptions and no accuracy is needed. - fontbbox = pdfarray { 0, 0, 0, 0 } - end - local encoding = pdfdictionary { - Type = pdfconstant("Encoding"), - Differences = differences, - } - local tounicode = tounicodedictionary(details,indices,maxindex,basefontname,false) - 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"), - FontName = basefont, - Flags = 4, - ItalicAngle = 0, - } - local parent = pdfdictionary { - Type = pdfconstant("Font"), - Subtype = pdfconstant("Type3"), - Name = basefont, - FontBBox = fontbbox, - FontMatrix = fontmatrix, - CharProcs = pdfreference(pdfflushobject(charprocs)), - Encoding = pdfreference(pdfflushobject(encoding)), - FirstChar = minindex, - LastChar = maxindex, - Widths = pdfreference(pdfflushobject(widths)), - FontDescriptor = pdfreference(pdfflushobject(descriptor)), - Resources = resources, - ToUnicode = tounicode and pdfreference(pdfflushstreamobject(tounicode)), - } - pdfflushobject(object,parent) - if reset then - reset() - end - end - - end - -end - --- writingmode - -local usedfonts = fonts.hashes.identifiers -- for now -local noffonts = 0 - --- The main injector. - --- here we need to test for sharing otherwise we reserve too many --- objects - -local getstreamhash = fonts.handlers.otf.getstreamhash -local loadstreamdata = fonts.handlers.otf.loadstreamdata - --- we can actually now number upwards (so not use fontid in /F) - -local objects = setmetatableindex(function(t,k) - local v - if type(k) == "number" then - local h = getstreamhash(k) - v = rawget(t,h) - if not v then - v = pdfreserveobject() - t[h] = v - end - if trace_fonts then - report_fonts("font id %i bound to hash %s and object %i",k,h,v) - end - else - -- no problem as it can be svg only - -- report_fonts("fatal error, hash %s asked but not used",k,h,v) - v = pdfreserveobject() - t[k] = v - end - return v -end) - -local n = 0 - -local names = setmetatableindex(function(t,k) - local v - if type(k) == "number" then - local h = getstreamhash(k) - v = rawget(t,h) - if not v then - n = n + 1 - v = n - t[h] = v - end - if trace_fonts then - report_fonts("font id %i bound to hash %s and name %i",k,h,n) - end - end - t[k] = v - return v -end) - -function lpdf.flushfonts() - - local mainfonts = { } - - statistics.starttiming(objects) - - for fontid, used in sortedhash(lpdf.usedcharacters) do - - -- for a bitmap we need a different hash unless we stick to a fixed high - -- resolution which makes much sense - - local hash = getstreamhash(fontid) - if hash then - local parent = mainfonts[hash] - if not parent then - local fontdata = usedfonts[fontid] - local rawdata = fontdata.shared and fontdata.shared.rawdata - local resources = fontdata.resources - local properties = fontdata.properties -- writingmode and type3 - local parameters = fontdata.parameters -- used in type3 - if not rawdata then - -- we have a virtual font that loaded directly ... at some point i will - -- sort this out (in readanddefine we need to do a bit more) .. the problem - -- is that we have a hybrid font then - for xfontid, xfontdata in next, fonts.hashes.identifiers do - if fontid ~= xfontid then - local xhash = getstreamhash(xfontid) - if hash == xhash then - rawdata = xfontdata.shared and xfontdata.shared.rawdata - if rawdata then - resources = xfontdata.resources - properties = xfontdata.properties - parameters = xfontdata.parameters - break - end - end - end - end - end - if rawdata then - parent = { - hash = hash, - fontdata = fontdata, - filename = resources.filename or properties.filename or "unset", - indices = { }, - rawdata = rawdata, - properties = properties, -- we assume consistency - parameters = parameters, -- we assume consistency - streams = { }, - objectnumber = objects[hash], - basefontname = subsetname(properties.psname or properties.name or "unset"), - name = names[hash], - } - mainfonts[hash] = parent - noffonts = noffonts + 1 - end - end - if parent then - local indices = parent.indices - for k in next, used do - indices[k] = true - end - end - end - end - - -- this is no not yet ok for tfm / type 1 .. we need to move the nested blobs ourside the loop - - for hash, details in sortedhash(mainfonts) do - local filename = details.filename - if next(details.indices) then - if trace_fonts then - report_fonts("embedding %a hashed as %a",filename,hash) - end - local properties = details.properties - local bitmap = properties.usedbitmap - local method = properties.method -- will be pk | pdf | svg | ... - if bitmap or method then - local format = "type3" - local writer = mainwriters[format] - if writer then - if trace_fonts then - report_fonts("using main writer %a",format) - end - writer(details) - end - else - local format = properties.format - local writer = mainwriters[format] - if not writer then - -- This will move to the tpk module where we will also deal - -- with bitmaps then. - local encoding, pfbfile, encfile = getmapentry(filename) - if trace_fonts then - report_fonts("file %a resolved to encoding %a and file %a",filename,encoding,pfbfile) - end - if encoding and pfbfile then - filename = pfbfile - format = "type1" - -- - -- another (temp) hack - local size = details.fontdata.parameters.size - local factor = details.fontdata.parameters.factor - local descriptions = { } - local characters = details.fontdata.characters - -- - local names, _, _, metadata = fonts.constructors.handlers.pfb.loadvector(pfbfile) - local reverse = table.swapped(names) - local vector = encoding.vector - local indices = details.indices - local remapped = { } - local factor = bpfactor * size / 65536 - for k, v in next, indices do - local name = vector[k] - local index = reverse[name] or 0 - local width = factor * (characters[k].width or 0) - descriptions[k] = { - width = width, - index = index, - name = name, - } - remapped[index] = true - end - details.indices = remapped - -- - details.rawdata.descriptions = descriptions - details.filename = filename - details.rawdata.metadata = { } - -- - properties.filename = filename - properties.format = format - writer = mainwriters[format] - end - end - if not writer then - local pfbfile = file.replacesuffix(filename,"pfb") - if encoding and pfbfile then - filename = pfbfile - format = "type1" - -- - -- another (temp) hack - local size = details.fontdata.parameters.size - local factor = details.fontdata.parameters.factor - local descriptions = { } - local characters = details.fontdata.characters - -- - local names, _, _, metadata = fonts.constructors.handlers.pfb.loadvector(pfbfile) - local reverse = table.swapped(names) - local vector = encoding.vector - local indices = details.indices - local remapped = { } - local factor = bpfactor * size / 65536 - for k, v in next, indices do - local name = vector[k] - local index = reverse[name] or 0 - local width = factor * (characters[k].width or 0) - descriptions[k] = { - width = width, - index = index, - name = name, - } - remapped[index] = true - end - details.indices = remapped - -- - details.rawdata.descriptions = descriptions - details.filename = filename - details.rawdata.metadata = { } - -- - properties.filename = filename - properties.format = format - writer = mainwriters[format] - end - end - if writer then - if trace_fonts then - report_fonts("using main writer %a",format) - end - -- better move this test to the writers .. cleaner - local streams = loadstreamdata(details.fontdata) - if streams and streams.fontheader and streams.names then - details.streams = streams - writer(details) - details.streams = { } - elseif trace_fonts then - -- can be ok for e.g. emoji - report_fonts("no streams in %a",filename) - end - -- free some memory - else -- if trace_fonts then - report_fonts("no %a writer for %a",format,filename) - end - end - else -- not problem for svg ... - -- report_fonts("no indices for %a",filename) - end - if trace_fonts then - report_fonts("embedded indices: % t",table.sortedkeys(details.indices)) - end - mainfonts[details.hash] = false -- done - end - - statistics.stoptiming(objects) - -end - -statistics.register("font embedding time",function() - if noffonts > 0 then - return format("%s seconds, %s fonts", statistics.elapsedtime(objects),noffonts) - end -end) - --- this is temporary - -local done = false - -updaters.register("backend.update.pdf",function() - if not done then - function pdf.getfontobjnum (k) return objects[k] end - function pdf.getfontname (k) return names [k] end - function pdf.includechar () end -- maybe, when we need it - function pdf.includefont () end -- maybe, when we need it - function pdf.includecharlist () end -- maybe, when we need it - function pdf.setomitcidset (v) includecidset = not toboolean(v) end - function pdf.setomitcharset () end -- we don't need that in lmtx - function pdf.setsuppressoptionalinfo() end -- we don't need that in lmtx - function pdf.mapfile (n) loadmapfile(n) end - function pdf.mapline (n) loadmapline(n) end - -- this will change - lpdf.registerdocumentfinalizer(lpdf.flushfonts,1,"wrapping up fonts") - done = true - end -end) diff --git a/tex/context/base/mkiv/lpdf-img.lmt b/tex/context/base/mkiv/lpdf-img.lmt new file mode 100644 index 000000000..fc53740f6 --- /dev/null +++ b/tex/context/base/mkiv/lpdf-img.lmt @@ -0,0 +1,1341 @@ +if not modules then modules = { } end modules ['lpdf-img'] = { + version = 1.001, + optimize = true, + 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" +} + +-- This started as an experiment but has potential for some (cached) optimizations. +-- At some point we can also use it for fonts. For small images performance is ok +-- with pure lua but for bigger images we can use some helpers. Normally in a +-- typesetting workflow non-interlaced images are used. One should convert +-- interlaced images to more efficient non-interlaced ones (ok, we can cache +-- them if needed). +-- +-- The \LUA\ code is slightly optimized so we could have done with less lines if +-- we wanted but best gain a little. The idea is that we collect striped (in stages) +-- so that we can play with substitutions. + +local type = type +local concat, move = table.concat, table.move +local ceil, min = math.ceil, math.min +local char, byte, find, gmatch = string.char, string.byte, string.find, string.gmatch +local idiv = number.idiv +local band, rshift = bit32.band, bit32.rshift + +local loaddata = io.loaddata +local setmetatableindex = table.setmetatableindex +local formatters = string.formatters + +local streams = utilities.streams +local openstring = streams.openstring +local readstring = streams.readstring +local readbytetable = streams.readbytetable + +local newreader = io.newreader + +local tobytetable = string.bytetable + +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 pdfverbose = lpdf.verbose + +local pdfmajorversion = lpdf.majorversion +local pdfminorversion = lpdf.minorversion + +local createimage = images.create + +local zlibcompress = (xzip or zlib).compress +local zlibdecompress = (xzip or zlib).decompress + +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 + +-- todo: load from a virtual file + +local function loadcontent(filename,method) + return method == "string" and filename or loaddata(filename) +end + +local function newcontent(filename,method) + return newreader(filename,method) +end + +-- + +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,method) + 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 = loadcontent(filename,method) + 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 + transform = specification.transform, + nolength = true, + nobbox = true, + notype = true, + stream = content, + attr = xobject(), + } + end + +end + +do + + function injectors.jp2(specification,method) + 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 = loadcontent(filename,method) + 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 + transform = specification.transform, + 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 pngapplyfilter = pngdecode.applyfilter + local pngsplitmask = pngdecode.splitmask + local pnginterlace = pngdecode.interlace + local pngexpand = pngdecode.expand + local pngtocmyk = pngdecode.tocmyk + + local filtermask, decodemask, decodestrip, transpose, expand, tocmyk + + local newindex = lua.newindex + local newtable = lua.newtable + + local function newoutput(size) + if newindex then + return newindex(size,0) + end + local t = newtable and newtable(size,0) or { } + for i=1,size do + t[i] = 0 + end + return t + end + + local function convert(t) + if type(t) == "table" then + for i=1,#t do + local ti = t[i] + if ti ~= "" then -- soon gone + t[i] = chars[ti] + end + end + return concat(t) + else + return t + end + end + + local function zero(t,k) + return 0 + end + + local function applyfilter(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] = "" + 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 + 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 + return t + end + + local filtermask_l = function (content,xsize,ysize,colordepth,colorspace,hasfilter) + local mask = { } + local bytes = colordepth == 16 and 2 or 1 + local bpp = colorspace == "DeviceRGB" and 3 or 1 + local length = #content + local size = ysize * xsize * ((bpp+1)*bytes + (hasfilter and 1 or 0)) + local n = 1 + local l = 1 + if bytes == 2 then + if bpp == 1 then + for i=1,ysize do + if hasfilter then + content[n] = "" ; n = n + 1 + end + for j=1,xsize do + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + mask[l] = chars[content[n]] ; l = l + 1 + content[n] = "" ; n = n + 1 + mask[l] = chars[content[n]] ; l = l + 1 + content[n] = "" ; n = n + 1 + end + end + elseif bpp == 3 then + for i=1,ysize do + if hasfilter then + content[n] = "" ; n = n + 1 + end + for j=1,xsize do + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + mask[l] = chars[content[n]] ; l = l + 1 + content[n] = "" ; n = n + 1 + mask[l] = chars[content[n]] ; l = l + 1 + content[n] = "" ; n = n + 1 + end + end + else + return "", "" + end + else + if bpp == 1 then + for i=1,ysize do + if hasfilter then + content[n] = "" ; n = n + 1 + end + for j=1,xsize do + content[n] = chars[content[n]] ; n = n + 1 + mask[l] = chars[content[n]] ; l = l + 1 + content[n] = "" ; n = n + 1 + end + end + elseif bpp == 3 then + for i=1,ysize do + if hasfilter then + content[n] = "" ; n = n + 1 + end + for j=1,xsize do + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + content[n] = chars[content[n]] ; n = n + 1 + mask[l] = chars[content[n]] ; l = l + 1 + content[n] = "" ; n = n + 1 + end + end + else + return "", "" + end + end + return concat(content), concat(mask) + end + + local decodemask_l = function(content,xsize,ysize,colordepth,colorspace) + local bytes = colordepth == 16 and 2 or 1 + local bpp = colorspace == "DeviceRGB" and 3 or 1 + local slice = bytes*(bpp+1) + local length = #content + local size = ysize * xsize * ((bpp+1)*bytes + 1) -- assume filter + content = openstring(content) + content = readbytetable(content,length) + setmetatableindex(content,zero) + applyfilter(content,xsize,ysize,slice) + content, mask = filtermask(content,xsize,ysize,colordepth,colorspace,true) + return content, mask + end + + local filtermask_c = function(content,xsize,ysize,colordepth,colorspace) + local bytes = colordepth == 16 and 2 or 1 + local bpp = colorspace == "DeviceRGB" and 3 or 1 + return pngsplitmask(content,xsize,ysize,bpp,bytes) + end + + local decodemask_c = function(content,xsize,ysize,colordepth,colorspace) + local mask = true + local filter = false + local bytes = colordepth == 16 and 2 or 1 + local bpp = colorspace == "DeviceRGB" and 3 or 1 + local slice = bytes * (bpp + 1) -- always a mask + content = pngapplyfilter(content,xsize,ysize,slice) + return pngsplitmask(content,xsize,ysize,bpp,bytes,mask,filter) + end + + local function decodestrip_l(s,nx,ny,slice) + local input = readbytetable(s,ny*(nx*slice+1)) + setmetatableindex(input,zero) + applyfilter(input,nx,ny,slice) + return input, true + end + + local function decodestrip_c(s,nx,ny,slice) + local input = readstring(s,ny*(nx*slice+1)) + input = pngapplyfilter(input,nx,ny,slice) + return input, false + end + + local xstart = { 0, 4, 0, 2, 0, 1, 0 } + local ystart = { 0, 0, 4, 0, 2, 0, 1 } + local xstep = { 8, 8, 4, 4, 2, 2, 1 } + local ystep = { 8, 8, 8, 4, 4, 2, 2 } + + local xblock = { 8, 4, 4, 2, 2, 1, 1 } + local yblock = { 8, 8, 4, 4, 2, 2, 1 } + + local function transpose_l(xsize,ysize,slice,pass,input,output,filter) + local xstart = xstart[pass] + local xstep = xstep[pass] + local ystart = ystart[pass] + local ystep = ystep[pass] + local nx = idiv(xsize + xstep - xstart - 1,xstep) + local ny = idiv(ysize + ystep - ystart - 1,ystep) + local offset = filter and 1 or 0 + local xstep = xstep * slice + local xstart = xstart * slice + local xsize = xsize * slice + local target = ystart * xsize + xstart + 1 + local ystep = ystep * xsize + local start = 1 + local plus = nx * xstep + local step = plus - xstep + if not output then + output = newoutput(xsize*(parts or slice)*ysize) + end + if slice == 1 then + for j=0,ny-1 do + start = start + offset + local target = target + j * ystep + for target=target,target+step,xstep do + output[target] = input[start] + start = start + slice + end + end + elseif slice == 2 then + for j=0,ny-1 do + start = start + offset + local target = target + j * ystep + for target=target,target+step,xstep do + output[target] = input[start] + output[target+1] = input[start+1] + start = start + slice + end + end + elseif slice == 3 then + for j=0,ny-1 do + start = start + offset + local target = target + j * ystep + for target=target,target+step,xstep do + output[target] = input[start] + output[target+1] = input[start+1] + output[target+2] = input[start+2] + start = start + slice + end + end + elseif slice == 4 then + for j=0,ny-1 do + start = start + offset + local target = target + j * ystep + for target=target,target+step,xstep do + output[target] = input[start] + output[target+1] = input[start+1] + output[target+2] = input[start+2] + output[target+3] = input[start+3] + start = start + slice + end + end + else + local delta = slice - 1 + for j=0,ny-1 do + start = start + offset + local target = target + j * ystep + for target=target,target+step,xstep do + move(input,start,start+delta,target,output) + start = start + slice + end + end + end + return output; + end + + local transpose_c = pnginterlace + + -- print(band(rshift(v,4),0x03),extract(v,4,2)) + -- print(band(rshift(v,6),0x03),extract(v,6,2)) + + local function expand_l(t,xsize,ysize,parts,run,factor,filter) + local size = ysize * xsize + 1 -- a bit of overshoot, needs testing, probably a few bytes us ok + local xline = filter and (run+1) or run + local f = filter and 1 or 0 + local l = xline - 1 + local n = 1 + local o = newoutput(size) + local k = 0 + if factor then + if parts == 4 then + for i=1,ysize do + for j=n+f,n+l do + local v = t[j] + if v == 0 then + k = k + 2 + else + k = k + 1 ; o[k] = extract4(v,4) * 0x11 + k = k + 1 ; o[k] = extract4(v,0) * 0x11 + end + end + k = i * xsize + n = n + xline + end + elseif parts == 2 then + for i=1,ysize do + for j=n+f,n+l do + local v = t[j] + if v == 0 then + k = k + 4 + else + k = k + 1 ; o[k] = extract2(v,6) * 0x55 + k = k + 1 ; o[k] = extract2(v,4) * 0x55 + k = k + 1 ; o[k] = extract2(v,2) * 0x55 + k = k + 1 ; o[k] = extract2(v,0) * 0x55 + end + end + k = i * xsize + n = n + xline + end + else + for i=1,ysize do + for j=n+f,n+l do + local v = t[j] + if v == 0 then + k = k + 8 + else + k = k + 1 ; if band(v,0x80) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,7) * 0xFF + k = k + 1 ; if band(v,0x40) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,6) * 0xFF + k = k + 1 ; if band(v,0x20) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,5) * 0xFF + k = k + 1 ; if band(v,0x10) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,4) * 0xFF + k = k + 1 ; if band(v,0x08) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,3) * 0xFF + k = k + 1 ; if band(v,0x04) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,2) * 0xFF + k = k + 1 ; if band(v,0x02) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,1) * 0xFF + k = k + 1 ; if band(v,0x01) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,0) * 0xFF + end + end + k = i * xsize + n = n + xline + end + end + else + if parts == 4 then + for i=1,ysize do + for j=n+f,n+l do + local v = t[j] + if v == 0 then + k = k + 2 + else + k = k + 1 ; o[k] = extract4(v,4) + k = k + 1 ; o[k] = extract4(v,0) + end + end + k = i * xsize + n = n + xline + end + elseif parts == 2 then + for i=1,ysize do + for j=n+f,n+l do + local v = t[j] + if v == 0 then + k = k + 4 + else + k = k + 1 ; o[k] = extract2(v,6) + k = k + 1 ; o[k] = extract2(v,4) + k = k + 1 ; o[k] = extract2(v,2) + k = k + 1 ; o[k] = extract2(v,0) + end + end + k = i * xsize + n = n + xline + end + else + for i=1,ysize do + for j=n+f,n+l do + local v = t[j] + if v == 0 then + k = k + 8 + else + k = k + 1 ; if band(v,0x80) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,7) + k = k + 1 ; if band(v,0x40) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,6) + k = k + 1 ; if band(v,0x20) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,5) + k = k + 1 ; if band(v,0x10) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,4) + k = k + 1 ; if band(v,0x08) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,3) + k = k + 1 ; if band(v,0x04) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,2) + k = k + 1 ; if band(v,0x02) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,1) + k = k + 1 ; if band(v,0x01) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,0) + end + end + k = i * xsize + n = n + xline + end + end + end + for i=size,xsize * ysize +1,-1 do + o[i] = nil + end + return o, false + end + + local expand_c = pngexpand + + local function analyze(colordepth,colorspace,palette,mask) + -- return 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 + + -- 1 6 4 6 2 6 4 6 + -- 7 7 7 7 7 7 7 7 + -- 5 6 5 6 5 6 5 6 + -- 7 7 7 7 7 7 7 7 + -- 3 6 4 6 3 6 4 6 + -- 7 7 7 7 7 7 7 7 + -- 5 6 5 6 5 6 5 6 + -- 7 7 7 7 7 7 7 7 + + local function deinterlace(content,xsize,ysize,colordepth,colorspace,palette,mask) + local slice, parts, factor = analyze(colordepth,colorspace,palette,mask) + if slice then + content = openstring(zlibdecompress(content)) + local filter = false + local output = false + for pass=1,7 do + local xstart = xstart[pass] + local xstep = xstep[pass] + local ystart = ystart[pass] + local ystep = ystep[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, filter + if parts then + local nxx = ceil(nx*parts/8) + input, filter = decodestrip(content,nxx,ny,slice) + input, filter = expand(input,nx,ny,parts,nxx,factor,filter) + else + input, filter = decodestrip(content,nx,ny,slice) + end + output = transpose(xsize,ysize,slice,pass,input,output,filter) + end + -- if pass == 3 then + -- break -- still looks ok, could be nice for a preroll + -- end + end + return output, 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 full(t,k) local v = "\xFF" t[k] = v return v end + + local function expandvector(transparent) + local s = openstring(transparent) + local n = #transparent + local r = { } + for i=0,n-1 do + r[i] = readstring(s,1) -- readchar + end + setmetatableindex(r,full) + return r + end + + local function createmask_l(content,palette,transparent,xsize,ysize,colordepth,colorspace) + if palette then + local r = expandvector(transparent) + local size = xsize*ysize + local len = ceil(xsize*colordepth/8) + 1 + local o = newoutput(xsize*ysize) + local u = setmetatableindex(zero) + content = zlibdecompress(content) + content = openstring(content) + for i=0,ysize-1 do + local t = readbytetable(content,len) + local k = i * 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] + end + elseif colordepth == 4 then + for j=2,len do + local v = t[j] + k = k + 1 ; o[k] = r[extract4(v,4)] + k = k + 1 ; o[k] = r[extract4(v,0)] + end + elseif colordepth == 2 then + for j=2,len do + local v = t[j] + k = k + 1 ; o[k] = r[extract2(v,6)] + k = k + 1 ; o[k] = r[extract2(v,4)] + k = k + 1 ; o[k] = r[extract2(v,2)] + k = k + 1 ; o[k] = r[extract2(v,0)] + end + else + for j=2,len do + local v = t[j] + k = k + 1 ; o[k] = r[extract1(v,7)] + k = k + 1 ; o[k] = r[extract1(v,6)] + k = k + 1 ; o[k] = r[extract1(v,5)] + k = k + 1 ; o[k] = r[extract1(v,4)] + k = k + 1 ; o[k] = r[extract1(v,3)] + k = k + 1 ; o[k] = r[extract1(v,2)] + k = k + 1 ; o[k] = r[extract1(v,1)] + k = k + 1 ; o[k] = r[extract1(v,0)] + end + end + u = t + end + return concat(o,"",1,size) + end + end + + local function createmask_c(content,palette,transparent,xsize,ysize,colordepth,colorspace) + if palette then + local r = expandvector(transparent) + local size = xsize*ysize + local len = ceil(xsize*colordepth/8) + local o = newoutput(size) + content = zlibdecompress(content) + content = pngapplyfilter(content,len,ysize,1) -- nostrip (saves copy) + content = openstring(content) + for i=0,ysize-1 do + local t = readbytetable(content,len) + local k = i * xsize + if colordepth == 8 then + for j=1,len do + local v = t[j] + k = k + 1 ; o[k] = r[v] + end + elseif colordepth == 4 then + for j=1,len do + local v = t[j] + k = k + 1 ; o[k] = r[extract4(v,4)] + k = k + 1 ; o[k] = r[extract4(v,0)] + end + elseif colordepth == 2 then + for j=1,len do + local v = t[j] + k = k + 1 ; o[k] = r[extract2(v,6)] + k = k + 1 ; o[k] = r[extract2(v,4)] + k = k + 1 ; o[k] = r[extract2(v,2)] + k = k + 1 ; o[k] = r[extract2(v,0)] + end + else + for j=1,len do + local v = t[j] + k = k + 1 ; o[k] = r[extract1(v,7)] + k = k + 1 ; o[k] = r[extract1(v,6)] + k = k + 1 ; o[k] = r[extract1(v,5)] + k = k + 1 ; o[k] = r[extract1(v,4)] + k = k + 1 ; o[k] = r[extract1(v,3)] + k = k + 1 ; o[k] = r[extract1(v,2)] + k = k + 1 ; o[k] = r[extract1(v,1)] + k = k + 1 ; o[k] = r[extract1(v,0)] + end + end + end + return concat(o,"",1,size) + end + end + + local function tocmyk_l(content,colordepth) + local l = #content + local t = { } + local n = 0 + if colordepth == 8 then + for i=1,l,3 do + local r, g, b = byte(content,i,i+2) + n = n + 1 ; t[n] = char(255-r,255-g,255-b,0) -- a tad faster than chars[...] + end + else + for i=1,l,6 do + local r1, r2, g1, g2, b1, b2 = byte(content,i,i+5) + n = n + 1 ; t[n] = char(255-r1,255-r2,255-g1,255-g2,255-b1,255-b2,0,0) + end + end + return concat(t) + end + + local tocmyk_c = pngtocmyk or tocmyk_l + + local function converttocmyk(content,colorspace,colordepth) + if colorspace == "DeviceRGB" and colordepth == 8 or colordepth == 16 then + local done = tocmyk(content,colordepth) + if done then + content = done + colorspace = "DeviceCMYK" + end + end + return content, colorspace + end + + local function switch(v) + if v then + filtermask = filtermask_l + decodemask = decodemask_l + decodestrip = decodestrip_l + transpose = transpose_l + expand = expand_l + createmask = createmask_l + tocmyk = tocmyk_l + else + filtermask = filtermask_c + decodemask = decodemask_c + decodestrip = decodestrip_c + transpose = transpose_c + expand = expand_c + createmask = createmask_c + tocmyk = tocmyk_c + end + end + + if pngapplyfilter then + switch(false) + directives.register("graphics.png.purelua",switch) + else + switch(true) + end + + local alwaysdecode = false -- trucky with palettes + local compresslevel = 3 + + directives.register("graphics.png.recompress", function(v) + alwaysdecode = v + end) + + directives.register("graphics.png.compresslevel", function(v) + v = tonumber(v) + if compresslevel >= 0 or compresslevel <= 9 then + compresslevel = v + end + end) + + function injectors.png(specification,method) -- todo: method in 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 = newcontent(filename,method) + 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 enforcecmyk = specification.enforcecmyk + 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 -- tricky, might go away + local filter = pdfconstant("FlateDecode") + 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 + report_png("you'd better use a version > 1.2") + return + -- 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 + if not (colordepth == 8 or colordepth == 16) then + report_png("mask can't be split from the image") + return + end -- get rid of bpp: + content, mask = filtermask(r,xsize,ysize,colordepth,colorspace,false) + else + content = convert(r) -- can be in deinterlace if needed + end + if enforcecmyk then + content, colorspace = converttocmyk(content,colorspace,colordepth) + end + if compresslevel > 0 then + content = zlibcompress(content,compresslevel) + else + filter = nil + end + decode = true + elseif mask then + if not (colordepth == 8 or colordepth == 16) then + report_png("mask can't be split from the image") + return + end + content = zlibdecompress(content) + content, mask = decodemask(content,xsize,ysize,colordepth,colorspace) + if enforcecmyk and not palette then + content, colorspace = converttocmyk(content,colorspace,colordepth) + end + if compresslevel > 0 then + content = zlibcompress(content,compresslevel) + else + filter = nil + end + decode = true -- we don't copy the filter byte + elseif transparent then + -- in test suite + -- how about decode/recompress here + if palette then + mask = createmask(content,palette,transparent,xsize,ysize,colordepth,colorspace) + else + pallette = false + end + elseif decode or (enforcecmyk and not palette) then + -- this one needs checking + local bytes = analyze(colordepth,colorspace) + if bytes then + content = zlibdecompress(content) + content = decodestrip(openstring(content),xsize,ysize,bytes) + if enforcecmyk and not palette then + content, colorspace = converttocmyk(content,colorspace,colordepth) + end + if compresslevel > 0 then + content = zlibcompress(content,compresslevel) + else + filter = nil + end + else + return + end + decode = true -- due to enforcecmyk + else + -- print("PASS ON") + end + if palette then + local colorspace = "DeviceRGB" + local nofbytes = 3 + if enforcecmyk then + palette = converttocmyk(palette,colorspace,8) + colorspace = "DeviceCMYK" + nofbytes = 4 + end + palette = pdfarray { + pdfconstant("Indexed"), + pdfconstant(colorspace), + idiv(#palette,nofbytes), + 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 = filter, + 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 + if specification.colorref then + xobject.ColorSpace = pdfreference(specification.colorref) + end + local width = specification.width or xsize * 65536 + local height = specification.height or ysize * 65536 + return createimage { + bbox = { 0, 0, width/xsize, height/ysize }, -- mandate + transform = specification.transform, + 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 + elseif what == "indexed" then + s = 1 + elseif what == "index" then + d = specification.index + s = - s + end + if s > 0 then + 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]] + -- n = n + 1 ; t[n] = char(c[1],c[2],c[3]) -- test this + 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]] + -- n = n + 1 ; t[n] = char(c[1],c[2],c[3],c[4]) -- test this + end + end + end + return concat(t) + else + local z = d[0] and 0 or 1 + if s == -1 then + local f = formatters["%02X"] + for i=z,#d do + n = n + 1 ; t[n] = f(d[i]) + end + elseif s == -2 then + local f = formatters["%02X%02X%02X"] + for i=z,#d do + local c = d[i] + n = n + 1 ; t[n] = f(c[1],c[2],c[3]) + end + elseif s == -3 then + local f = formatters["%02X%02X%02X%02X"] + for i=z,#d do + local c = d[i] + n = n + 1 ; t[n] = f(c[1],c[2],c[3],c[4]) + end + end + return "<" .. concat(t," ") .. ">" + end + return "" + 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 index = specification.index + local content = pack(specification,index and "indexed" or "data") + local mask = specification.mask + local colorspace = pdfconstant(colorspace) + if index then + colorspace = pdfarray { + pdfconstant("Indexed"), + colorspace, + #index + (index[0] and 0 or -1), -- upper index + pdfverbose(pack(specification,"index")) + } + end + local xobject = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Image"), + BBox = pdfarray { 0, 0, xsize, ysize }, + Width = xsize, + Height = ysize, + BitsPerComponent = colordepth, + ColorSpace = 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 + + backends.pdf.codeinjections.bitmap = injectors.bitmap + +end + +-- local function validcompression(data) +-- local d = utilities.streams.openstring(data) +-- local b1 = utilities.streams.readbyte(d) +-- local b2 = utilities.streams.readbyte(d) +-- print(b1,b2) +-- if (b1 * 256 + b2) % 31 ~= 0 then +-- return false, "no zlib compressed file" +-- end +-- local method = band(b1,15) +-- if method ~= 8 then +-- return false, "method 8 expected" +-- end +-- local detail = band(rshift(b1,4),15) +-- if detail > 7 then +-- return false, "window 32 expected" +-- end +-- local preset = band(rshift(b2,5),1) +-- if preset ~= 0 then +-- return false, "unexpected preset dictionary" +-- end +-- return true +-- end diff --git a/tex/context/base/mkiv/lpdf-img.lua b/tex/context/base/mkiv/lpdf-img.lua deleted file mode 100644 index fc53740f6..000000000 --- a/tex/context/base/mkiv/lpdf-img.lua +++ /dev/null @@ -1,1341 +0,0 @@ -if not modules then modules = { } end modules ['lpdf-img'] = { - version = 1.001, - optimize = true, - 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" -} - --- This started as an experiment but has potential for some (cached) optimizations. --- At some point we can also use it for fonts. For small images performance is ok --- with pure lua but for bigger images we can use some helpers. Normally in a --- typesetting workflow non-interlaced images are used. One should convert --- interlaced images to more efficient non-interlaced ones (ok, we can cache --- them if needed). --- --- The \LUA\ code is slightly optimized so we could have done with less lines if --- we wanted but best gain a little. The idea is that we collect striped (in stages) --- so that we can play with substitutions. - -local type = type -local concat, move = table.concat, table.move -local ceil, min = math.ceil, math.min -local char, byte, find, gmatch = string.char, string.byte, string.find, string.gmatch -local idiv = number.idiv -local band, rshift = bit32.band, bit32.rshift - -local loaddata = io.loaddata -local setmetatableindex = table.setmetatableindex -local formatters = string.formatters - -local streams = utilities.streams -local openstring = streams.openstring -local readstring = streams.readstring -local readbytetable = streams.readbytetable - -local newreader = io.newreader - -local tobytetable = string.bytetable - -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 pdfverbose = lpdf.verbose - -local pdfmajorversion = lpdf.majorversion -local pdfminorversion = lpdf.minorversion - -local createimage = images.create - -local zlibcompress = (xzip or zlib).compress -local zlibdecompress = (xzip or zlib).decompress - -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 - --- todo: load from a virtual file - -local function loadcontent(filename,method) - return method == "string" and filename or loaddata(filename) -end - -local function newcontent(filename,method) - return newreader(filename,method) -end - --- - -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,method) - 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 = loadcontent(filename,method) - 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 - transform = specification.transform, - nolength = true, - nobbox = true, - notype = true, - stream = content, - attr = xobject(), - } - end - -end - -do - - function injectors.jp2(specification,method) - 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 = loadcontent(filename,method) - 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 - transform = specification.transform, - 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 pngapplyfilter = pngdecode.applyfilter - local pngsplitmask = pngdecode.splitmask - local pnginterlace = pngdecode.interlace - local pngexpand = pngdecode.expand - local pngtocmyk = pngdecode.tocmyk - - local filtermask, decodemask, decodestrip, transpose, expand, tocmyk - - local newindex = lua.newindex - local newtable = lua.newtable - - local function newoutput(size) - if newindex then - return newindex(size,0) - end - local t = newtable and newtable(size,0) or { } - for i=1,size do - t[i] = 0 - end - return t - end - - local function convert(t) - if type(t) == "table" then - for i=1,#t do - local ti = t[i] - if ti ~= "" then -- soon gone - t[i] = chars[ti] - end - end - return concat(t) - else - return t - end - end - - local function zero(t,k) - return 0 - end - - local function applyfilter(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] = "" - 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 - 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 - return t - end - - local filtermask_l = function (content,xsize,ysize,colordepth,colorspace,hasfilter) - local mask = { } - local bytes = colordepth == 16 and 2 or 1 - local bpp = colorspace == "DeviceRGB" and 3 or 1 - local length = #content - local size = ysize * xsize * ((bpp+1)*bytes + (hasfilter and 1 or 0)) - local n = 1 - local l = 1 - if bytes == 2 then - if bpp == 1 then - for i=1,ysize do - if hasfilter then - content[n] = "" ; n = n + 1 - end - for j=1,xsize do - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - mask[l] = chars[content[n]] ; l = l + 1 - content[n] = "" ; n = n + 1 - mask[l] = chars[content[n]] ; l = l + 1 - content[n] = "" ; n = n + 1 - end - end - elseif bpp == 3 then - for i=1,ysize do - if hasfilter then - content[n] = "" ; n = n + 1 - end - for j=1,xsize do - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - mask[l] = chars[content[n]] ; l = l + 1 - content[n] = "" ; n = n + 1 - mask[l] = chars[content[n]] ; l = l + 1 - content[n] = "" ; n = n + 1 - end - end - else - return "", "" - end - else - if bpp == 1 then - for i=1,ysize do - if hasfilter then - content[n] = "" ; n = n + 1 - end - for j=1,xsize do - content[n] = chars[content[n]] ; n = n + 1 - mask[l] = chars[content[n]] ; l = l + 1 - content[n] = "" ; n = n + 1 - end - end - elseif bpp == 3 then - for i=1,ysize do - if hasfilter then - content[n] = "" ; n = n + 1 - end - for j=1,xsize do - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - content[n] = chars[content[n]] ; n = n + 1 - mask[l] = chars[content[n]] ; l = l + 1 - content[n] = "" ; n = n + 1 - end - end - else - return "", "" - end - end - return concat(content), concat(mask) - end - - local decodemask_l = function(content,xsize,ysize,colordepth,colorspace) - local bytes = colordepth == 16 and 2 or 1 - local bpp = colorspace == "DeviceRGB" and 3 or 1 - local slice = bytes*(bpp+1) - local length = #content - local size = ysize * xsize * ((bpp+1)*bytes + 1) -- assume filter - content = openstring(content) - content = readbytetable(content,length) - setmetatableindex(content,zero) - applyfilter(content,xsize,ysize,slice) - content, mask = filtermask(content,xsize,ysize,colordepth,colorspace,true) - return content, mask - end - - local filtermask_c = function(content,xsize,ysize,colordepth,colorspace) - local bytes = colordepth == 16 and 2 or 1 - local bpp = colorspace == "DeviceRGB" and 3 or 1 - return pngsplitmask(content,xsize,ysize,bpp,bytes) - end - - local decodemask_c = function(content,xsize,ysize,colordepth,colorspace) - local mask = true - local filter = false - local bytes = colordepth == 16 and 2 or 1 - local bpp = colorspace == "DeviceRGB" and 3 or 1 - local slice = bytes * (bpp + 1) -- always a mask - content = pngapplyfilter(content,xsize,ysize,slice) - return pngsplitmask(content,xsize,ysize,bpp,bytes,mask,filter) - end - - local function decodestrip_l(s,nx,ny,slice) - local input = readbytetable(s,ny*(nx*slice+1)) - setmetatableindex(input,zero) - applyfilter(input,nx,ny,slice) - return input, true - end - - local function decodestrip_c(s,nx,ny,slice) - local input = readstring(s,ny*(nx*slice+1)) - input = pngapplyfilter(input,nx,ny,slice) - return input, false - end - - local xstart = { 0, 4, 0, 2, 0, 1, 0 } - local ystart = { 0, 0, 4, 0, 2, 0, 1 } - local xstep = { 8, 8, 4, 4, 2, 2, 1 } - local ystep = { 8, 8, 8, 4, 4, 2, 2 } - - local xblock = { 8, 4, 4, 2, 2, 1, 1 } - local yblock = { 8, 8, 4, 4, 2, 2, 1 } - - local function transpose_l(xsize,ysize,slice,pass,input,output,filter) - local xstart = xstart[pass] - local xstep = xstep[pass] - local ystart = ystart[pass] - local ystep = ystep[pass] - local nx = idiv(xsize + xstep - xstart - 1,xstep) - local ny = idiv(ysize + ystep - ystart - 1,ystep) - local offset = filter and 1 or 0 - local xstep = xstep * slice - local xstart = xstart * slice - local xsize = xsize * slice - local target = ystart * xsize + xstart + 1 - local ystep = ystep * xsize - local start = 1 - local plus = nx * xstep - local step = plus - xstep - if not output then - output = newoutput(xsize*(parts or slice)*ysize) - end - if slice == 1 then - for j=0,ny-1 do - start = start + offset - local target = target + j * ystep - for target=target,target+step,xstep do - output[target] = input[start] - start = start + slice - end - end - elseif slice == 2 then - for j=0,ny-1 do - start = start + offset - local target = target + j * ystep - for target=target,target+step,xstep do - output[target] = input[start] - output[target+1] = input[start+1] - start = start + slice - end - end - elseif slice == 3 then - for j=0,ny-1 do - start = start + offset - local target = target + j * ystep - for target=target,target+step,xstep do - output[target] = input[start] - output[target+1] = input[start+1] - output[target+2] = input[start+2] - start = start + slice - end - end - elseif slice == 4 then - for j=0,ny-1 do - start = start + offset - local target = target + j * ystep - for target=target,target+step,xstep do - output[target] = input[start] - output[target+1] = input[start+1] - output[target+2] = input[start+2] - output[target+3] = input[start+3] - start = start + slice - end - end - else - local delta = slice - 1 - for j=0,ny-1 do - start = start + offset - local target = target + j * ystep - for target=target,target+step,xstep do - move(input,start,start+delta,target,output) - start = start + slice - end - end - end - return output; - end - - local transpose_c = pnginterlace - - -- print(band(rshift(v,4),0x03),extract(v,4,2)) - -- print(band(rshift(v,6),0x03),extract(v,6,2)) - - local function expand_l(t,xsize,ysize,parts,run,factor,filter) - local size = ysize * xsize + 1 -- a bit of overshoot, needs testing, probably a few bytes us ok - local xline = filter and (run+1) or run - local f = filter and 1 or 0 - local l = xline - 1 - local n = 1 - local o = newoutput(size) - local k = 0 - if factor then - if parts == 4 then - for i=1,ysize do - for j=n+f,n+l do - local v = t[j] - if v == 0 then - k = k + 2 - else - k = k + 1 ; o[k] = extract4(v,4) * 0x11 - k = k + 1 ; o[k] = extract4(v,0) * 0x11 - end - end - k = i * xsize - n = n + xline - end - elseif parts == 2 then - for i=1,ysize do - for j=n+f,n+l do - local v = t[j] - if v == 0 then - k = k + 4 - else - k = k + 1 ; o[k] = extract2(v,6) * 0x55 - k = k + 1 ; o[k] = extract2(v,4) * 0x55 - k = k + 1 ; o[k] = extract2(v,2) * 0x55 - k = k + 1 ; o[k] = extract2(v,0) * 0x55 - end - end - k = i * xsize - n = n + xline - end - else - for i=1,ysize do - for j=n+f,n+l do - local v = t[j] - if v == 0 then - k = k + 8 - else - k = k + 1 ; if band(v,0x80) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,7) * 0xFF - k = k + 1 ; if band(v,0x40) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,6) * 0xFF - k = k + 1 ; if band(v,0x20) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,5) * 0xFF - k = k + 1 ; if band(v,0x10) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,4) * 0xFF - k = k + 1 ; if band(v,0x08) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,3) * 0xFF - k = k + 1 ; if band(v,0x04) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,2) * 0xFF - k = k + 1 ; if band(v,0x02) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,1) * 0xFF - k = k + 1 ; if band(v,0x01) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,0) * 0xFF - end - end - k = i * xsize - n = n + xline - end - end - else - if parts == 4 then - for i=1,ysize do - for j=n+f,n+l do - local v = t[j] - if v == 0 then - k = k + 2 - else - k = k + 1 ; o[k] = extract4(v,4) - k = k + 1 ; o[k] = extract4(v,0) - end - end - k = i * xsize - n = n + xline - end - elseif parts == 2 then - for i=1,ysize do - for j=n+f,n+l do - local v = t[j] - if v == 0 then - k = k + 4 - else - k = k + 1 ; o[k] = extract2(v,6) - k = k + 1 ; o[k] = extract2(v,4) - k = k + 1 ; o[k] = extract2(v,2) - k = k + 1 ; o[k] = extract2(v,0) - end - end - k = i * xsize - n = n + xline - end - else - for i=1,ysize do - for j=n+f,n+l do - local v = t[j] - if v == 0 then - k = k + 8 - else - k = k + 1 ; if band(v,0x80) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,7) - k = k + 1 ; if band(v,0x40) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,6) - k = k + 1 ; if band(v,0x20) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,5) - k = k + 1 ; if band(v,0x10) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,4) - k = k + 1 ; if band(v,0x08) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,3) - k = k + 1 ; if band(v,0x04) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,2) - k = k + 1 ; if band(v,0x02) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,1) - k = k + 1 ; if band(v,0x01) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,0) - end - end - k = i * xsize - n = n + xline - end - end - end - for i=size,xsize * ysize +1,-1 do - o[i] = nil - end - return o, false - end - - local expand_c = pngexpand - - local function analyze(colordepth,colorspace,palette,mask) - -- return 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 - - -- 1 6 4 6 2 6 4 6 - -- 7 7 7 7 7 7 7 7 - -- 5 6 5 6 5 6 5 6 - -- 7 7 7 7 7 7 7 7 - -- 3 6 4 6 3 6 4 6 - -- 7 7 7 7 7 7 7 7 - -- 5 6 5 6 5 6 5 6 - -- 7 7 7 7 7 7 7 7 - - local function deinterlace(content,xsize,ysize,colordepth,colorspace,palette,mask) - local slice, parts, factor = analyze(colordepth,colorspace,palette,mask) - if slice then - content = openstring(zlibdecompress(content)) - local filter = false - local output = false - for pass=1,7 do - local xstart = xstart[pass] - local xstep = xstep[pass] - local ystart = ystart[pass] - local ystep = ystep[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, filter - if parts then - local nxx = ceil(nx*parts/8) - input, filter = decodestrip(content,nxx,ny,slice) - input, filter = expand(input,nx,ny,parts,nxx,factor,filter) - else - input, filter = decodestrip(content,nx,ny,slice) - end - output = transpose(xsize,ysize,slice,pass,input,output,filter) - end - -- if pass == 3 then - -- break -- still looks ok, could be nice for a preroll - -- end - end - return output, 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 full(t,k) local v = "\xFF" t[k] = v return v end - - local function expandvector(transparent) - local s = openstring(transparent) - local n = #transparent - local r = { } - for i=0,n-1 do - r[i] = readstring(s,1) -- readchar - end - setmetatableindex(r,full) - return r - end - - local function createmask_l(content,palette,transparent,xsize,ysize,colordepth,colorspace) - if palette then - local r = expandvector(transparent) - local size = xsize*ysize - local len = ceil(xsize*colordepth/8) + 1 - local o = newoutput(xsize*ysize) - local u = setmetatableindex(zero) - content = zlibdecompress(content) - content = openstring(content) - for i=0,ysize-1 do - local t = readbytetable(content,len) - local k = i * 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] - end - elseif colordepth == 4 then - for j=2,len do - local v = t[j] - k = k + 1 ; o[k] = r[extract4(v,4)] - k = k + 1 ; o[k] = r[extract4(v,0)] - end - elseif colordepth == 2 then - for j=2,len do - local v = t[j] - k = k + 1 ; o[k] = r[extract2(v,6)] - k = k + 1 ; o[k] = r[extract2(v,4)] - k = k + 1 ; o[k] = r[extract2(v,2)] - k = k + 1 ; o[k] = r[extract2(v,0)] - end - else - for j=2,len do - local v = t[j] - k = k + 1 ; o[k] = r[extract1(v,7)] - k = k + 1 ; o[k] = r[extract1(v,6)] - k = k + 1 ; o[k] = r[extract1(v,5)] - k = k + 1 ; o[k] = r[extract1(v,4)] - k = k + 1 ; o[k] = r[extract1(v,3)] - k = k + 1 ; o[k] = r[extract1(v,2)] - k = k + 1 ; o[k] = r[extract1(v,1)] - k = k + 1 ; o[k] = r[extract1(v,0)] - end - end - u = t - end - return concat(o,"",1,size) - end - end - - local function createmask_c(content,palette,transparent,xsize,ysize,colordepth,colorspace) - if palette then - local r = expandvector(transparent) - local size = xsize*ysize - local len = ceil(xsize*colordepth/8) - local o = newoutput(size) - content = zlibdecompress(content) - content = pngapplyfilter(content,len,ysize,1) -- nostrip (saves copy) - content = openstring(content) - for i=0,ysize-1 do - local t = readbytetable(content,len) - local k = i * xsize - if colordepth == 8 then - for j=1,len do - local v = t[j] - k = k + 1 ; o[k] = r[v] - end - elseif colordepth == 4 then - for j=1,len do - local v = t[j] - k = k + 1 ; o[k] = r[extract4(v,4)] - k = k + 1 ; o[k] = r[extract4(v,0)] - end - elseif colordepth == 2 then - for j=1,len do - local v = t[j] - k = k + 1 ; o[k] = r[extract2(v,6)] - k = k + 1 ; o[k] = r[extract2(v,4)] - k = k + 1 ; o[k] = r[extract2(v,2)] - k = k + 1 ; o[k] = r[extract2(v,0)] - end - else - for j=1,len do - local v = t[j] - k = k + 1 ; o[k] = r[extract1(v,7)] - k = k + 1 ; o[k] = r[extract1(v,6)] - k = k + 1 ; o[k] = r[extract1(v,5)] - k = k + 1 ; o[k] = r[extract1(v,4)] - k = k + 1 ; o[k] = r[extract1(v,3)] - k = k + 1 ; o[k] = r[extract1(v,2)] - k = k + 1 ; o[k] = r[extract1(v,1)] - k = k + 1 ; o[k] = r[extract1(v,0)] - end - end - end - return concat(o,"",1,size) - end - end - - local function tocmyk_l(content,colordepth) - local l = #content - local t = { } - local n = 0 - if colordepth == 8 then - for i=1,l,3 do - local r, g, b = byte(content,i,i+2) - n = n + 1 ; t[n] = char(255-r,255-g,255-b,0) -- a tad faster than chars[...] - end - else - for i=1,l,6 do - local r1, r2, g1, g2, b1, b2 = byte(content,i,i+5) - n = n + 1 ; t[n] = char(255-r1,255-r2,255-g1,255-g2,255-b1,255-b2,0,0) - end - end - return concat(t) - end - - local tocmyk_c = pngtocmyk or tocmyk_l - - local function converttocmyk(content,colorspace,colordepth) - if colorspace == "DeviceRGB" and colordepth == 8 or colordepth == 16 then - local done = tocmyk(content,colordepth) - if done then - content = done - colorspace = "DeviceCMYK" - end - end - return content, colorspace - end - - local function switch(v) - if v then - filtermask = filtermask_l - decodemask = decodemask_l - decodestrip = decodestrip_l - transpose = transpose_l - expand = expand_l - createmask = createmask_l - tocmyk = tocmyk_l - else - filtermask = filtermask_c - decodemask = decodemask_c - decodestrip = decodestrip_c - transpose = transpose_c - expand = expand_c - createmask = createmask_c - tocmyk = tocmyk_c - end - end - - if pngapplyfilter then - switch(false) - directives.register("graphics.png.purelua",switch) - else - switch(true) - end - - local alwaysdecode = false -- trucky with palettes - local compresslevel = 3 - - directives.register("graphics.png.recompress", function(v) - alwaysdecode = v - end) - - directives.register("graphics.png.compresslevel", function(v) - v = tonumber(v) - if compresslevel >= 0 or compresslevel <= 9 then - compresslevel = v - end - end) - - function injectors.png(specification,method) -- todo: method in 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 = newcontent(filename,method) - 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 enforcecmyk = specification.enforcecmyk - 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 -- tricky, might go away - local filter = pdfconstant("FlateDecode") - 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 - report_png("you'd better use a version > 1.2") - return - -- 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 - if not (colordepth == 8 or colordepth == 16) then - report_png("mask can't be split from the image") - return - end -- get rid of bpp: - content, mask = filtermask(r,xsize,ysize,colordepth,colorspace,false) - else - content = convert(r) -- can be in deinterlace if needed - end - if enforcecmyk then - content, colorspace = converttocmyk(content,colorspace,colordepth) - end - if compresslevel > 0 then - content = zlibcompress(content,compresslevel) - else - filter = nil - end - decode = true - elseif mask then - if not (colordepth == 8 or colordepth == 16) then - report_png("mask can't be split from the image") - return - end - content = zlibdecompress(content) - content, mask = decodemask(content,xsize,ysize,colordepth,colorspace) - if enforcecmyk and not palette then - content, colorspace = converttocmyk(content,colorspace,colordepth) - end - if compresslevel > 0 then - content = zlibcompress(content,compresslevel) - else - filter = nil - end - decode = true -- we don't copy the filter byte - elseif transparent then - -- in test suite - -- how about decode/recompress here - if palette then - mask = createmask(content,palette,transparent,xsize,ysize,colordepth,colorspace) - else - pallette = false - end - elseif decode or (enforcecmyk and not palette) then - -- this one needs checking - local bytes = analyze(colordepth,colorspace) - if bytes then - content = zlibdecompress(content) - content = decodestrip(openstring(content),xsize,ysize,bytes) - if enforcecmyk and not palette then - content, colorspace = converttocmyk(content,colorspace,colordepth) - end - if compresslevel > 0 then - content = zlibcompress(content,compresslevel) - else - filter = nil - end - else - return - end - decode = true -- due to enforcecmyk - else - -- print("PASS ON") - end - if palette then - local colorspace = "DeviceRGB" - local nofbytes = 3 - if enforcecmyk then - palette = converttocmyk(palette,colorspace,8) - colorspace = "DeviceCMYK" - nofbytes = 4 - end - palette = pdfarray { - pdfconstant("Indexed"), - pdfconstant(colorspace), - idiv(#palette,nofbytes), - 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 = filter, - 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 - if specification.colorref then - xobject.ColorSpace = pdfreference(specification.colorref) - end - local width = specification.width or xsize * 65536 - local height = specification.height or ysize * 65536 - return createimage { - bbox = { 0, 0, width/xsize, height/ysize }, -- mandate - transform = specification.transform, - 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 - elseif what == "indexed" then - s = 1 - elseif what == "index" then - d = specification.index - s = - s - end - if s > 0 then - 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]] - -- n = n + 1 ; t[n] = char(c[1],c[2],c[3]) -- test this - 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]] - -- n = n + 1 ; t[n] = char(c[1],c[2],c[3],c[4]) -- test this - end - end - end - return concat(t) - else - local z = d[0] and 0 or 1 - if s == -1 then - local f = formatters["%02X"] - for i=z,#d do - n = n + 1 ; t[n] = f(d[i]) - end - elseif s == -2 then - local f = formatters["%02X%02X%02X"] - for i=z,#d do - local c = d[i] - n = n + 1 ; t[n] = f(c[1],c[2],c[3]) - end - elseif s == -3 then - local f = formatters["%02X%02X%02X%02X"] - for i=z,#d do - local c = d[i] - n = n + 1 ; t[n] = f(c[1],c[2],c[3],c[4]) - end - end - return "<" .. concat(t," ") .. ">" - end - return "" - 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 index = specification.index - local content = pack(specification,index and "indexed" or "data") - local mask = specification.mask - local colorspace = pdfconstant(colorspace) - if index then - colorspace = pdfarray { - pdfconstant("Indexed"), - colorspace, - #index + (index[0] and 0 or -1), -- upper index - pdfverbose(pack(specification,"index")) - } - end - local xobject = pdfdictionary { - Type = pdfconstant("XObject"), - Subtype = pdfconstant("Image"), - BBox = pdfarray { 0, 0, xsize, ysize }, - Width = xsize, - Height = ysize, - BitsPerComponent = colordepth, - ColorSpace = 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 - - backends.pdf.codeinjections.bitmap = injectors.bitmap - -end - --- local function validcompression(data) --- local d = utilities.streams.openstring(data) --- local b1 = utilities.streams.readbyte(d) --- local b2 = utilities.streams.readbyte(d) --- print(b1,b2) --- if (b1 * 256 + b2) % 31 ~= 0 then --- return false, "no zlib compressed file" --- end --- local method = band(b1,15) --- if method ~= 8 then --- return false, "method 8 expected" --- end --- local detail = band(rshift(b1,4),15) --- if detail > 7 then --- return false, "window 32 expected" --- end --- local preset = band(rshift(b2,5),1) --- if preset ~= 0 then --- return false, "unexpected preset dictionary" --- end --- return true --- end diff --git a/tex/context/base/mkiv/lpdf-ini.lua b/tex/context/base/mkiv/lpdf-ini.lua index 8ece39cee..1f6dac938 100644 --- a/tex/context/base/mkiv/lpdf-ini.lua +++ b/tex/context/base/mkiv/lpdf-ini.lua @@ -445,10 +445,14 @@ do local f_key_null = formatters["/%s null"] local f_key_value = formatters["/%s %s"] - local f_key_dictionary = formatters["/%s << % t >>"] - local f_dictionary = formatters["<< % t >>"] - local f_key_array = formatters["/%s [ % t ]"] - local f_array = formatters["[ % t ]"] + -- local f_key_dictionary = formatters["/%s << % t >>"] + -- local f_dictionary = formatters["<< % t >>"] + local f_key_dictionary = formatters["/%s << %s >>"] + local f_dictionary = formatters["<< %s >>"] + -- local f_key_array = formatters["/%s [ % t ]"] + -- local f_array = formatters["[ % t ]"] + local f_key_array = formatters["/%s [ %s ]"] + local f_array = formatters["[ %s ]"] local f_key_number = formatters["/%s %N"] -- always with max 9 digits and integer is possible local f_tonumber = formatters["%N"] -- always with max 9 digits and integer is possible @@ -501,8 +505,9 @@ do if e then r[n+1] = e end + r = concat(r," ") if contentonly then - return concat(r," ") + return r elseif key then return f_key_dictionary(key,r) else @@ -550,8 +555,9 @@ do if e then r[tn+1] = e end + r = concat(r," ") if contentonly then - return concat(r, " ") + return r elseif key then return f_key_array(key,r) else diff --git a/tex/context/base/mkiv/lpdf-lmt.lmt b/tex/context/base/mkiv/lpdf-lmt.lmt new file mode 100644 index 000000000..61a194ca4 --- /dev/null +++ b/tex/context/base/mkiv/lpdf-lmt.lmt @@ -0,0 +1,2835 @@ +if not modules then modules = { } end modules ['lpdf-lmt'] = { + version = 1.001, + optimize = true, + 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" +} + +-- The code below was originally in back-lpd.lua but it makes more sense in +-- this namespace. I will rename variables. +-- +-- There is no way that a lua based backend can compete with the original one +-- for relative simple text runs. And we're talking seconds here on say 500 +-- pages with paragraphs alternativng between three fonts and colors. But such +-- documents are rare so in practice we are quite okay, especially because in +-- ConTeXt we can gain quite a bit elsewhere. So, when we loose 30% on such +-- simple documents, we break even on for instance the manual, and gain 30% on +-- Thomas's turture test (also for other reasons). But .. who knows what magic +-- I can cook up in due time. + +-- If you consider this complex, watch: +-- +-- https://www.youtube.com/watch?v=6H-cAzfB2qo +-- +-- or in distractionmode: +-- +-- https://www.youtube.com/watch?v=TYuTE_1jvvE +-- https://www.youtube.com/watch?v=nnicGKX3lvM +-- +-- For the moment we have to support the built in backend as well as the alternative. So +-- the next interface is suboptimal and will change at some time. At that moment I will +-- also optimize and extend. + +local type, next, unpack, tonumber, rawget = type, next, unpack, tonumber, rawget +local char, rep, find = string.char, string.rep, string.find +local formatters, splitupstring = string.formatters, string.splitup +local band, extract = bit32.band, bit32.extract +local concat, sortedhash = table.concat, table.sortedhash +local setmetatableindex = table.setmetatableindex +local loaddata = io.loaddata + +local bpfactor = number.dimenfactors.bp + +local md5HEX = md5.HEX +local osuuid = os.uuid +local zlibcompress = (xzip or zlib).compress + +local nuts = nodes.nuts +local tonut = nodes.tonut + +local getdata = nuts.getdata +local getsubtype = nuts.getsubtype +local getwhd = nuts.getwhd +local flushlist = nuts.flush_list + +local pdfincludeimage = lpdf.includeimage +local pdfgetfontname = lpdf.getfontname +local pdfgetfontobjnumber = lpdf.getfontobjnumber + +local pdfreserveobject = lpdf.reserveobject +local pdfpagereference = lpdf.pagereference +local pdfflushobject = lpdf.flushobject +local pdfsharedobject = lpdf.shareobjectreference +local pdfreference = lpdf.reference +local pdfdictionary = lpdf.dictionary +local pdfarray = lpdf.array +local pdfconstant = lpdf.constant +local pdfflushstreamobject = lpdf.flushstreamobject +local pdfliteral = lpdf.literal -- not to be confused with a whatsit! + +local pdf_pages = pdfconstant("Pages") +local pdf_page = pdfconstant("Page") +local pdf_xobject = pdfconstant("XObject") +local pdf_form = pdfconstant("Form") + +local fonthashes = fonts.hashes +local characters = fonthashes.characters +local descriptions = fonthashes.descriptions +local parameters = fonthashes.parameters +local properties = fonthashes.properties + +local report = logs.reporter("backend") + +-- used variables + +local pdf_h, pdf_v +local need_tm, need_tf, cur_tmrx, cur_factor, cur_f, cur_e +local need_width, need_mode, done_width, done_mode +local mode +local f_pdf_cur, f_pdf, fs_cur, fs, f_cur +local tj_delta, cw +local usedfonts, usedxforms, usedximages, usedxgroups +local getxformname, getximagename +local boundingbox, shippingmode, objectnumber +local tmrx, tmry, tmsx, tmsy, tmtx, tmty +local cmrx, cmry, cmsx, cmsy, cmtx, cmty +local tmef + +local function usefont(t,k) -- a bit redundant hash + local v = pdfgetfontname(k) + t[k] = v + return v +end + +local function reset_variables(specification) + pdf_h, pdf_v = 0, 0 + cmrx, cmry = 1.0, 1.0 + cmsx, cmsy = 0.0, 0.0 + cmtx, cmty = 0.0, 0.0 + tmrx, tmry = 1.0, 1.0 + tmsx, tmsy = 0.0, 0.0 + tmtx, tmty = 0.0, 0.0 + tmef = 1.0 + need_tm = false + need_tf = false + need_width = 0 + need_mode = 0 + done_width = false + done_mode = false + mode = "page" + shippingmode = specification.shippingmode + objectnumber = specification.objectnumber + cur_tmrx = 0.0 + f_cur = 0 + f_pdf_cur = 0 -- nullfont + f_pdf = 0 -- nullfont + fs_cur = 0 + fs = 0 + cur_factor = 0 + cur_f = false + cur_e = false + tj_delta = 0.0 + cw = 0.0 + usedfonts = setmetatableindex(usefont) + usedxforms = { } + usedximages = { } + -- usedxgroups = { } + boundingbox = specification.boundingbox +end + +-- buffer + +local buffer = lua.newtable(1024,0) -- { } +local b = 0 + +local function reset_buffer() + b = 0 +end + +local function flush_buffer() + b = 0 +end + +-- fonts + +local fontcharacters +local fontdescriptions +local fontparameters +local fontproperties +local usedcharacters = setmetatableindex("table") +local pdfcharacters + +local horizontalmode = true +----- widefontmode = true +local scalefactor = 1 +local threshold = 655360 +local thresfactor = 100 +local tjfactor = 100 / 65536 + +lpdf.usedcharacters = usedcharacters + +local function updatefontstate(font) + fontcharacters = characters[font] + fontdescriptions = descriptions[font] + fontparameters = parameters[font] + fontproperties = properties[font] + local size = fontparameters.size -- or bad news + local designsize = fontparameters.designsize or size + pdfcharacters = usedcharacters[font] + horizontalmode = fontparameters.writingmode ~= "vertical" + -- widefontmode = fontproperties.encodingbytes == 2 + scalefactor = (designsize/size) * tjfactor + local fthreshold = fontproperties.threshold + threshold = (fthreshold and (size * fthreshold / 100)) or 655360 + -- when we bolden the threshold should be smaller .. a hack .. i need to redo all this + if (fontparameters.extendfactor or 1) == 1 then + -- we're probably okay + elseif fontparameters.hshift or fontparameters.vshift then + -- we could be okay + else + -- some vf magic going on + threshold = threshold / 5 + end +end + +-- helpers + +local f_cm = formatters["%.6N %.6N %.6N %.6N %.6N %.6N cm"] +local f_tm = formatters["%.6N %.6N %.6N %.6N %.6N %.6N Tm"] + +local saved_text_pos_v = 0 +local saved_text_pos_h = 0 + +local function begin_text() + saved_text_pos_h = pdf_h + saved_text_pos_v = pdf_v + b = b + 1 ; buffer[b] = "BT" + need_tf = true + need_width = 0 + need_mode = 0 + mode = "text" +end + +local function end_text() + if done_width then + b = b + 1 ; buffer[b] = "0 w" + done_width = false + end + if done_mode then + b = b + 1 ; buffer[b] = "0 Tr" + done_mode = false + end + b = b + 1 ; buffer[b] = "ET" + pdf_h = saved_text_pos_h + pdf_v = saved_text_pos_v + mode = "page" +end + +local saved_chararray_pos_h +local saved_chararray_pos_v + +local saved_b = 0 + +local function begin_chararray() + saved_chararray_pos_h = pdf_h + saved_chararray_pos_v = pdf_v + cw = horizontalmode and saved_chararray_pos_h or - saved_chararray_pos_v + tj_delta = 0 + saved_b = b + b = b + 1 ; buffer[b] = " [" + mode = "chararray" +end + +local function end_chararray() + b = b + 1 ; buffer[b] = "] TJ" + buffer[saved_b] = concat(buffer,"",saved_b,b) + b = saved_b + pdf_h = saved_chararray_pos_h + pdf_v = saved_chararray_pos_v + mode = "text" +end + +local function begin_charmode() + b = b + 1 ; buffer[b] = "<" + mode = "char" +end + +local function end_charmode() + b = b + 1 ; buffer[b] = ">" + mode = "chararray" +end + +local function calc_pdfpos(h,v) + -- mostly char + if mode == "page" then + cmtx = h - pdf_h + cmty = v - pdf_v + return h ~= pdf_h or v ~= pdf_v + elseif mode == "text" then + tmtx = h - saved_text_pos_h + tmty = v - saved_text_pos_v + return h ~= pdf_h or v ~= pdf_v + elseif horizontalmode then + tmty = v - saved_text_pos_v + tj_delta = cw - h + return tj_delta ~= 0 or v ~= pdf_v + else + tmtx = h - saved_text_pos_h + tj_delta = cw + v + return tj_delta ~= 0 or h ~= pdf_h + end +end + +local function pdf_set_pos(h,v) + local move = calc_pdfpos(h,v) + if move then + b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor) + pdf_h = pdf_h + cmtx + pdf_v = pdf_v + cmty + end +end + +local function pdf_reset_pos() + if mode == "page" then + cmtx = - pdf_h + cmty = - pdf_v + if pdf_h == 0 and pdf_v == 0 then + return + end + elseif mode == "text" then + tmtx = - saved_text_pos_h + tmty = - saved_text_pos_v + if pdf_h == 0 and pdf_v == 0 then + return + end + elseif horizontalmode then + tmty = - saved_text_pos_v + tj_delta = cw + if tj_delta == 0 and pdf_v == 0 then + return + end + else + tmtx = - saved_text_pos_h + tj_delta = cw + if tj_delta == 0 and pdf_h == 0 then + return + end + end + b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor) + pdf_h = pdf_h + cmtx + pdf_v = pdf_v + cmty +end + +local function pdf_set_pos_temp(h,v) + local move = calc_pdfpos(h,v) + if move then + b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor) + end +end + +-- these dummy returns makes using them a bit faster + +local function pdf_end_string_nl() + if mode == "char" then + end_charmode() + return end_chararray() + elseif mode == "chararray" then + return end_chararray() + end +end + +local function pdf_goto_textmode() + if mode == "page" then + pdf_reset_pos() + return begin_text() + elseif mode ~= "text" then + if mode == "char" then + end_charmode() + return end_chararray() + else -- if mode == "chararray" then + return end_chararray() + end + end +end + +local function pdf_goto_pagemode() + if mode ~= "page" then + if mode == "char" then + end_charmode() + end_chararray() + return end_text() + elseif mode == "chararray" then + end_chararray() + return end_text() + elseif mode == "text" then + return end_text() + end + end +end + +local function pdf_goto_fontmode() + if mode == "char" then + end_charmode() + end_chararray() + end_text() + elseif mode == "chararray" then + end_chararray() + end_text() + elseif mode == "text" then + end_text() + end + pdf_reset_pos() + mode = "page" +end + +-- characters + +local flushcharacter do + + local round = math.round + + -- across pages ... todo: clean up because we don't need to pass the font + -- as fontparameters already has checked / set it we can also have a variable + -- for it so + + local naturalwidth = nil + local hshift = false + local vshift = false + + -- local naturalwidths = setmetatableindex(function(t,font) + -- local d = descriptions[font] + -- local c = characters[font] + -- local f = parameters[font].hfactor + -- local v = setmetatableindex(function(t,char) + -- local w + -- local e = d and d[char] + -- if e then + -- w = e.width + -- if w then + -- w = w * f + -- end + -- end + -- if not w then + -- e = c[char] + -- if e then + -- w = e.width or 0 + -- end + -- end + -- if not w then + -- w = 0 + -- end + -- t[char] = w + -- return w + -- end) + -- t[font] = v + -- return v + -- end) + + local naturalwidths = setmetatableindex(function(t,font) + local d = descriptions[font] + local c = characters[font] + local f = parameters[font].hfactor + local v = setmetatableindex(function(t,char) + local w + local e = c[char] + if e then + w = e.width or 0 + end + if not w then + e = d and d[char] + if e then + w = e.width + if w then + w = w * f + end + end + end + if not w then + w = 0 + end + t[char] = w + return w + end) + t[font] = v + return v + end) + + local function setup_fontparameters(font,factor,f,e) + local slant = fontparameters.slantfactor or 0 + local extend = fontparameters.extendfactor or 1 + local squeeze = fontparameters.squeezefactor or 1 + local expand = 1 + factor / 1000000 + local format = fontproperties.format + if e then + extend = extend * e + end + tmef = expand + tmrx = expand * extend + tmsy = slant + tmry = squeeze + need_width = fontparameters.width or 0 + need_mode = fontparameters.mode or 0 + f_cur = font + f_pdf = usedfonts[font] -- cache + cur_factor = factor + cur_f = f + cur_e = e + tj_delta = 0 + fs = fontparameters.size * bpfactor + if f then + fs = fs * f + end + -- kind of special: + if format == "opentype" or format == "type1" then + fs = fs * 1000 / fontparameters.units -- can we avoid this ? + end + -- + naturalwidth = naturalwidths[font] + -- + hshift = fontparameters.hshift + vshift = fontparameters.vshift + end + + local f_width = formatters["%.6N w"] + local f_mode = formatters["%i Tr"] -- can be hash + local f_font = formatters["/F%i %.6N Tf"] -- can be hash + + local s_width = "0 w" + local s_mode = "0 Tr" + + local width_factor = 72.27 / 72000.0 + + local function set_font() + -- if need_width and need_width ~= 0 then + if need_width ~= 0 then + b = b + 1 ; buffer[b] = f_width(width_factor*need_width) + done_width = true + elseif done_width then + b = b + 1 ; buffer[b] = s_width + done_width = false + end + -- if need_mode and need_mode ~= 0 then + if need_mode ~= 0 then + b = b + 1 ; buffer[b] = f_mode(need_mode) + done_mode = true + elseif done_mode then + b = b + 1 ; buffer[b] = s_mode + done_mode = false + end + b = b + 1 ; buffer[b] = f_font(f_pdf,fs) + f_pdf_cur = f_pdf + fs_cur = fs + need_tf = false + need_tm = true + end + + local function set_textmatrix(h,v) + local move = calc_pdfpos(h,v) + if need_tm or move then + b = b + 1 ; buffer[b] = f_tm(tmrx, tmsx, tmsy, tmry, tmtx*bpfactor, tmty*bpfactor) + pdf_h = saved_text_pos_h + tmtx + pdf_v = saved_text_pos_v + tmty + need_tm = false + end + cur_tmrx = tmrx + end + + local f_hex_4 = formatters["%04X"] + local f_hex_2 = formatters["%02X"] + + local h_hex_4 = setmetatableindex(function(t,k) -- we already have this somewhere + if k < 256 then -- maybe 512 + -- not sparse in this range + for i=0,255 do + t[i] = f_hex_4(i) + end + return t[k] + else + local v = f_hex_4(k) + t[k] = v + return v + end + end) + local h_hex_2 = setmetatableindex(function(t,k) -- we already have this somewhere + local v = k < 256 and f_hex_2(k) or "00" + t[k] = v + return v + end) + + -- local trace_threshold = false trackers.register("backends.pdf.threshold", function(v) trace_threshold = v end) + + -- local f_skip = formatters["%.2N"] + + -- I will redo this mess ... we no longer have the mkiv pdf generator that we used in + -- luatex (a precursor to lmtx and also for comparison) but only in lmtx now so ... + -- time to move on I guess. + + flushcharacter = function(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) + if need_tf or font ~= f_cur or f_pdf ~= f_pdf_cur or fs ~= fs_cur or mode == "page" then + pdf_goto_textmode() + setup_fontparameters(font,factor,f,e) + set_font() + elseif cur_tmrx ~= tmrx or cur_factor ~= factor or cur_f ~= f or cur_e ~= e then + setup_fontparameters(font,factor,f,e) + need_tm = true + end + local move = calc_pdfpos(pos_h,pos_v) + + -- if trace_threshold then + -- report( + -- "font %i, char %C, factor %i, naturalwidth %p, move %l, tm %l, hpos %p, delta %p, threshold %p, cw %p", + -- font,char,factor,naturalwidth[char],move,need_tm,pos_h,tj_delta,threshold,cw + -- ) + -- end + + if move or need_tm then + if not need_tm then + if horizontalmode then + if (saved_text_pos_v + tmty) ~= pdf_v then + need_tm = true + elseif tj_delta >= threshold or tj_delta <= -threshold then + need_tm = true + end + else + if (saved_text_pos_h + tmtx) ~= pdf_h then + need_tm = true + elseif tj_delta >= threshold or tj_delta <= -threshold then + need_tm = true + end + end + end + + if hshift then pos_h = pos_h + hshift end + if vshift then pos_v = pos_v - vshift end + + if need_tm then + pdf_goto_textmode() + set_textmatrix(pos_h,pos_v) + begin_chararray() + move = calc_pdfpos(pos_h,pos_v) + end + if move then + local d = tj_delta * scalefactor + if d <= -0.5 or d >= 0.5 then + if mode == "char" then + end_charmode() + end + b = b + 1 ; buffer[b] = round(d) -- or f_skip(d) + end + cw = cw - tj_delta + end + end + + if mode == "chararray" then + begin_charmode() + end + + cw = cw + naturalwidth[char] * tmef + + local index = data.index or char + + b = b + 1 ; buffer[b] = font > 0 and h_hex_4[index] or h_hex_2[index] + + if not pdfcharacters[index] then + pdfcharacters[index] = true + end + + end + + flushfontchar = function(font,char,data) + local dummy = usedfonts[font] + local index = data.index or char + if not pdfcharacters[index] then + pdfcharacters[index] = true + end + return dummy + end + +end + +-- literals + +local flushliteral do + + local nodeproperties = nodes.properties.data + local literalvalues = nodes.literalvalues + + local originliteral_code = literalvalues.origin + local pageliteral_code = literalvalues.page + local alwaysliteral_code = literalvalues.always + local rawliteral_code = literalvalues.raw + local textliteral_code = literalvalues.text + local fontliteral_code = literalvalues.font + + flushliteral = function(current,pos_h,pos_v,mode,str) + if mode then + if not str then + mode, str = originliteral_code, mode + elseif mode == "mode" then + mode = literalvalues[str] + if mode == originliteral_code then + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + elseif mode == pageliteral_code then + pdf_goto_pagemode() + elseif mode == textliteral_code then + pdf_goto_textmode() + elseif mode == fontliteral_code then + pdf_goto_fontmode() + elseif mode == alwaysliteral_code then + pdf_end_string_nl() + need_tm = true + elseif mode == rawliteral_code then + pdf_end_string_nl() + end + return + else + mode = literalvalues[mode] + end + else + local p = nodeproperties[current] + if p then + str = p.data + mode = p.mode + else + str, mode = getdata(current) + end + end + if str and str ~= "" then + if mode == originliteral_code then + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + elseif mode == pageliteral_code then + pdf_goto_pagemode() + elseif mode == textliteral_code then + pdf_goto_textmode() + elseif mode == fontliteral_code then + pdf_goto_fontmode() + elseif mode == alwaysliteral_code then + pdf_end_string_nl() + need_tm = true + elseif mode == rawliteral_code then + pdf_end_string_nl() + else + report("check literal") + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + end + b = b + 1 ; buffer[b] = str + end + end + + updaters.register("backend.update.pdf",function() + function pdf.print(mode,str) + if str then + mode = literalvalues[mode] + else + mode, str = originliteral_code, mode + end + if str and str ~= "" then + if mode == originliteral_code then + pdf_goto_pagemode() + -- pdf_set_pos(pdf_h,pdf_v) + elseif mode == pageliteral_code then + pdf_goto_pagemode() + elseif mode == textliteral_code then + pdf_goto_textmode() + elseif mode == fontliteral_code then + pdf_goto_fontmode() + elseif mode == alwaysliteral_code then + pdf_end_string_nl() + need_tm = true + elseif mode == rawliteral_code then + pdf_end_string_nl() + else + pdf_goto_pagemode() + -- pdf_set_pos(pdf_h,pdf_v) + end + b = b + 1 ; buffer[b] = str + flush_buffer() + end + end + end) + +end + +-- grouping & orientation + +local flushsave, flushrestore, flushsetmatrix do + + local matrices = { } + local positions = { } + local nofpositions = 0 + local nofmatrices = 0 + + local f_matrix = formatters["%s 0 0 cm"] + + flushsave = function(current,pos_h,pos_v) + nofpositions = nofpositions + 1 + positions[nofpositions] = { pos_h, pos_v, nofmatrices } + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + b = b + 1 ; buffer[b] = "q" + end + + flushrestore = function(current,pos_h,pos_v) + if nofpositions < 1 then + return + end + local t = positions[nofpositions] + -- local h = pos_h - t[1] + -- local v = pos_v - t[2] + if shippingmode == "page" then + nofmatrices = t[3] + end + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + b = b + 1 ; buffer[b] = "Q" + nofpositions = nofpositions - 1 + end + + local function pdf_set_matrix(str,pos_h,pos_v) + if shippingmode == "page" then + local rx, sx, sy, ry = splitupstring(str," ") + if rx and ry and sx and ry then + rx, sx, sy, ry = tonumber(rx), tonumber(sx), tonumber(sy), tonumber(ry) + local tx = pos_h * (1 - rx) - pos_v * sy + local ty = pos_v * (1 - ry) - pos_h * sx + if nofmatrices > 0 then + local t = matrices[nofmatrices] + local r_x, s_x, s_y, r_y, te, tf = t[1], t[2], t[3], t[4], t[5], t[6] + rx, sx = rx * r_x + sx * s_y, rx * s_x + sx * r_y + sy, ry = sy * r_x + ry * s_y, sy * s_x + ry * r_y + tx, ty = tx * r_x + ty * s_y, tx * s_x + ty * r_y + end + nofmatrices = nofmatrices + 1 + matrices[nofmatrices] = { rx, sx, sy, ry, tx, ty } + end + end + end + + local nodeproperties = nodes.properties.data + + flushsetmatrix = function(current,pos_h,pos_v) + local str + if type(current) == "string" then + str = current + else + local p = nodeproperties[current] + if p then + str = p.matrix + else + str = getdata(current) -- for the moment + end + end + if str and str ~= "" then + pdf_set_matrix(str,pos_h,pos_v) + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + b = b + 1 ; buffer[b] = f_matrix(str) + end + end + + do + + local function hasmatrix() + return nofmatrices > 0 + end + + local function getmatrix() + if nofmatrices > 0 then + return unpack(matrices[nofmatrices]) + else + return 1, 0, 0, 1, 0, 0 + end + end + + updaters.register("backend.update.pdf",function() + pdf.hasmatrix = hasmatrix + pdf.getmatrix = getmatrix + end) + + end + + pushorientation = function(orientation,pos_h,pos_v,pos_r) + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + b = b + 1 ; buffer[b] = "q" + if orientation == 1 then + b = b + 1 ; buffer[b] = "0 -1 1 0 0 0 cm" -- 90 + elseif orientation == 2 then + b = b + 1 ; buffer[b] = "-1 0 0 -1 0 0 cm" -- 180 + elseif orientation == 3 then + b = b + 1 ; buffer[b] = "0 1 -1 0 0 0 cm" -- 270 + end + end + + poporientation = function(orientation,pos_h,pos_v,pos_r) + pdf_goto_pagemode() + pdf_set_pos(pos_h,pos_v) + b = b + 1 ; buffer[b] = "Q" + end + + -- pushorientation = function(orientation,pos_h,pos_v,pos_r) + -- flushsave(false,pos_h,pos_v) + -- if orientation == 1 then + -- flushsetmatrix("0 -1 1 0",pos_h,pos_v) + -- elseif orientation == 2 then + -- flushsetmatrix("-1 0 0 -1",pos_h,pos_v) + -- elseif orientation == 3 then + -- flushsetmatrix("0 1 -1 0",pos_h,pos_v) + -- end + -- end + + -- poporientation = function(orientation,pos_h,pos_v,pos_r) + -- flushrestore(false,pos_h,pos_v) + -- end + +end + +-- rules + +local flushedxforms = { } -- actually box resources but can also be direct +local localconverter = nil -- will be set + +local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do + + local rulecodes = nodes.rulecodes + local newrule = nodes.pool.rule + + local setprop = nuts.setprop + local getprop = nuts.getprop + + local normalrule_code = rulecodes.normal + local boxrule_code = rulecodes.box + local imagerule_code = rulecodes.image + local emptyrule_code = rulecodes.empty + local userrule_code = rulecodes.user + local overrule_code = rulecodes.over + local underrule_code = rulecodes.under + local fractionrule_code = rulecodes.fraction + local radicalrule_code = rulecodes.radical + local outlinerule_code = rulecodes.outline + + local rule_callback = callbacks.functions.process_rule + + local f_fm = formatters["/Fm%d Do"] + local f_im = formatters["/Im%d Do"] + local f_gr = formatters["/Gp%d Do"] + + local s_b = "q" + local s_e = "Q" + + local f_v = formatters["[] 0 d 0 J %.6N w 0 0 m %.6N 0 l S"] + local f_h = formatters["[] 0 d 0 J %.6N w 0 0 m 0 %.6N l S"] + + local f_f = formatters["0 0 %.6N %.6N re f"] + local f_o = formatters["[] 0 d 0 J 0 0 %.6N %.6N re S"] + local f_w = formatters["[] 0 d 0 J %.6N w 0 0 %.6N %.6N re S"] + + local f_b = formatters["%.6N w 0 %.6N %.6N %.6N re f"] + local f_f = formatters["[] 0 d 0 J %.6N w %.6N %.6N %.6N %.6N re S"] + + -- Historically the index is an object which is kind of bad. + + local boxresources, n = { }, 0 + + getxformname = function(index) + local l = boxresources[index] + if l then + return l.name + else + report("no box resource %S",index) + end + end + + updaters.register("backend.update.pdf",function() + pdf.getxformname = getxformname + end) + + local function saveboxresource(box,attributes,resources,immediate,kind,margin) + n = n + 1 + local immediate = true + local margin = margin or 0 -- or dimension + local objnum = pdfreserveobject() + local list = tonut(type(box) == "number" and tex.takebox(box) or box) + -- + local width, height, depth = getwhd(list) + -- + local l = { + width = width, + height = height, + depth = depth, + margin = margin, + attributes = attributes, + resources = resources, + list = nil, + type = kind, + name = n, + index = objnum, + objnum = objnum, + } + boxresources[objnum] = l + if immediate then + localconverter(list,"xform",objnum,l) + flushedxforms[objnum] = { true , objnum } + flushlist(list) + else + l.list = list + end + return objnum + end + + local function useboxresource(index,wd,ht,dp) + local l = boxresources[index] + if l then + if wd or ht or dp then + wd, ht, dp = wd or 0, ht or 0, dp or 0 + else + wd, ht, dp = l.width, l.height, l.depth + end + local rule = newrule(wd,ht,dp) -- newboxrule + rule.subtype = boxrule_code + setprop(tonut(rule),"index",index) + return rule, wd, ht, dp + else + report("no box resource %S",index) + end + end + + local function getboxresourcedimensions(index) + local l = boxresources[index] + if l then + return l.width, l.height, l.depth, l.margin + else + report("no box resource %S",index) + end + end + + local function getboxresourcebox(index) + local l = boxresources[index] + if l then + return l.list + end + end + + updaters.register("backend.update.tex",function() + tex.saveboxresource = saveboxresource + tex.useboxresource = useboxresource + tex.getboxresourcedimensions = getboxresourcedimensions + tex.getboxresourcebox = getboxresourcebox + end) + + -- a bit of a mess: index is now objnum but that has to change to a proper index + -- ... an engine inheritance + + local function flushpdfxform(current,pos_h,pos_v,pos_r,size_h,size_v) + -- object properties + local objnum = getprop(current,"index") + local name = getxformname(objnum) + local info = flushedxforms[objnum] + local r = boxresources[objnum] + if not info then + info = { false , objnum } + flushedxforms[objnum] = info + end + local wd, ht, dp = getboxresourcedimensions(objnum) + -- or: wd, ht, dp = r.width, r.height, r.depth + -- sanity check + local htdp = ht + dp + if wd == 0 or size_h == 0 or htdp == 0 or size_v == 0 then + return + end + -- calculate scale + local rx, ry = 1, 1 + if wd ~= size_h or htdp ~= size_v then + rx = size_h / wd + ry = size_v / htdp + end + -- flush the reference + usedxforms[objnum] = true + pdf_goto_pagemode() + calc_pdfpos(pos_h,pos_v) + tx = cmtx * bpfactor + ty = cmty * bpfactor + b = b + 1 ; buffer[b] = s_b + b = b + 1 ; buffer[b] = f_cm(rx,0,0,ry,tx,ty) + b = b + 1 ; buffer[b] = f_fm(name) + b = b + 1 ; buffer[b] = s_e + end + + -- place image also used in vf but we can use a different one if we need it + + local imagetypes = images.types -- pdf png jpg jp2 jbig2 stream memstream + local img_none = imagetypes.none + local img_pdf = imagetypes.pdf + local img_stream = imagetypes.stream + local img_memstream = imagetypes.memstream + + local one_bp = 65536 * bpfactor + + local imageresources, n = { }, 0 + + getximagename = function(index) + local l = imageresources[index] + if l then + return l.name + else + report("no image resource %S",index) + end + end + + updaters.register("backend.update.pdf",function() + pdf.getximagename = getximagename + end) + + -- Groups are flushed immediately but we can decide to make them into a + -- specific whatsit ... but not now. We could hash them if needed when + -- we use lot sof them in mp ... but not now. + + usedxgroups = { } + local groups = 0 + local group = nil + + flushgroup = function(content,bbox) + if not group then + group = pdfdictionary { + Type = pdfconstant("Group"), + S = pdfconstant("Transparency"), + } + end + local wrapper = pdfdictionary { + Type = pdf_xobject, + Subtype = pdf_form, + FormType = 1, + Group = group, + BBox = pdfarray(bbox), + Resources = lpdf.collectedresources { serialize = false }, + } + local objnum = pdfflushstreamobject(content,wrapper,false) + groups = groups + 1 + usedxgroups[groups] = objnum + return f_gr(groups) + end + + lpdf.flushgroup = flushgroup -- todo: access via driver in mlib-pps + + -- end of experiment + + local function flushpdfximage(current,pos_h,pos_v,pos_r,size_h,size_v) + + local width, + height, + depth = getwhd(current) + local total = height + depth + local transform = getprop(current,"transform") or 0 -- we never set it ... so just use rotation then + local index = getprop(current,"index") or 0 + local kind, + xorigin, + yorigin, + xsize, + ysize, + rotation, -- transform / orientation / rotation : it's a mess (i need to redo this) + objnum, + groupref = pdfincludeimage(index) -- needs to be sorted out, bad name (no longer mixed anyway) + + if not kind then + report("invalid image %S",index) + return + end + + local rx, sx, sy, ry, tx, ty = 1, 0, 0, 1, 0, 0 + + -- tricky: xsize and ysize swapped + + if kind == img_pdf or kind == img_stream or kind == img_memstream then + rx, ry, tx, ty = 1/xsize, 1/ysize, xorigin/xsize, yorigin/ysize + else + -- if kind == img_png then + -- -- if groupref > 0 and img_page_group_val == 0 then + -- -- img_page_group_val = groupref + -- -- end + -- end + rx, ry = bpfactor, bpfactor + end + + if band(transform,7) > 3 then + -- mirror + rx, tx = -rx, -tx + end + local t = band(transform + rotation,3) + if t == 0 then + -- nothing + elseif t == 1 then + -- rotation over 90 degrees (counterclockwise) + rx, sx, sy, ry, tx, ty = 0, rx, -ry, 0, -ty, tx + elseif t == 2 then + -- rotation over 180 degrees (counterclockwise) + rx, ry, tx, ty = -rx, -ry, -tx, -ty + elseif t == 3 then + -- rotation over 270 degrees (counterclockwise) + rx, sx, sy, ry, tx, ty = 0, -rx, ry, 0, ty, -tx + end + + rx = rx * width + sx = sx * total + sy = sy * width + ry = ry * total + tx = pos_h - tx * width + ty = pos_v - ty * total + + local t = transform + rotation + + if band(transform,7) > 3 then + t = t + 1 + end + + t = band(t,3) + + if t == 0 then + -- no transform + elseif t == 1 then + -- rotation over 90 degrees (counterclockwise) + tx = tx + width + elseif t == 2 then + -- rotation over 180 degrees (counterclockwise) + tx = tx + width + ty = ty + total + elseif t == 3 then + -- rotation over 270 degrees (counterclockwise) + ty = ty + total + end + + -- a flaw in original, can go: + -- + -- if img_page_group_val == 0 then + -- img_page_group_val = group_ref + -- end + + usedximages[index] = objnum -- hm + + pdf_goto_pagemode() + + calc_pdfpos(tx,ty) + + tx = cmtx * bpfactor + ty = cmty * bpfactor + + b = b + 1 ; buffer[b] = s_b + b = b + 1 ; buffer[b] = f_cm(rx,sx,sy,ry,tx,ty) + b = b + 1 ; buffer[b] = f_im(index) + b = b + 1 ; buffer[b] = s_e + end + + flushimage = function(index,width,height,depth,pos_h,pos_v) + + -- used in vf characters + + local total = height + depth + local kind, + xorigin, yorigin, + xsize, ysize, + rotation, + objnum, + groupref = pdfincludeimage(index) + + local rx = width / xsize + local sx = 0 + local sy = 0 + local ry = total / ysize + local tx = pos_h + -- to be sorted out + -- local ty = pos_v - depth + local ty = pos_v -- we assume that depth is dealt with in the caller (for now) + + usedximages[index] = objnum + + pdf_goto_pagemode() + + calc_pdfpos(tx,ty) + + tx = cmtx * bpfactor + ty = cmty * bpfactor + + b = b + 1 ; buffer[b] = s_b + b = b + 1 ; buffer[b] = f_cm(rx,sx,sy,ry,tx,ty) + b = b + 1 ; buffer[b] = f_im(index) + b = b + 1 ; buffer[b] = s_e + end + + -- For the moment we need this hack because the engine checks the 'image' + -- command in virtual fonts (so we use lua instead). + -- + -- These will be replaced by a new more advanced one ... some day ... or + -- never because the next are like the other engines and compensate for + -- small sizes which is needed for inaccurate viewers. + + flushrule = function(current,pos_h,pos_v,pos_r,size_h,size_v,subtype) + + if subtype == emptyrule_code then + return + elseif subtype == boxrule_code then + return flushpdfxform(current,pos_h,pos_v,pos_r,size_h,size_v) + elseif subtype == imagerule_code then + return flushpdfximage(current,pos_h,pos_v,pos_r,size_h,size_v) + end + if subtype == userrule_code or subtype >= overrule_code and subtype <= radicalrule_code then + pdf_goto_pagemode() + b = b + 1 ; buffer[b] = s_b + pdf_set_pos_temp(pos_h,pos_v) + rule_callback(current,size_h,size_v,pos_r) -- so we pass direction + b = b + 1 ; buffer[b] = s_e + return + end + + pdf_goto_pagemode() + + -- local saved_b = b + + b = b + 1 ; buffer[b] = s_b + + local dim_h = size_h * bpfactor + local dim_v = size_v * bpfactor + local rule + + if dim_v <= one_bp then + pdf_set_pos_temp(pos_h,pos_v + 0.5 * size_v) + rule = f_v(dim_v,dim_h) + elseif dim_h <= one_bp then + pdf_set_pos_temp(pos_h + 0.5 * size_h,pos_v) + rule = f_h(dim_h,dim_v) + else + pdf_set_pos_temp(pos_h,pos_v) + if subtype == outlinerule_code then + local linewidth = getdata(current) + if linewidth > 0 then + rule = f_w(linewidth * bpfactor,dim_h,dim_v) + else + rule = f_o(dim_h,dim_v) + end + else + rule = f_f(dim_h,dim_v) + end + end + + b = b + 1 ; buffer[b] = rule + b = b + 1 ; buffer[b] = s_e + + -- buffer[saved_b] = concat(buffer," ",saved_b,b) + -- b = saved_b + + end + + flushsimplerule = function(pos_h,pos_v,pos_r,size_h,size_v) + pdf_goto_pagemode() + + b = b + 1 ; buffer[b] = s_b + + local dim_h = size_h * bpfactor + local dim_v = size_v * bpfactor + local rule + + if dim_v <= one_bp then + pdf_set_pos_temp(pos_h,pos_v + 0.5 * size_v) + rule = f_v(dim_v,dim_h) + elseif dim_h <= one_bp then + pdf_set_pos_temp(pos_h + 0.5 * size_h,pos_v) + rule = f_h(dim_h,dim_v) + else + pdf_set_pos_temp(pos_h,pos_v) + rule = f_f(dim_h,dim_v) + end + + b = b + 1 ; buffer[b] = rule + b = b + 1 ; buffer[b] = s_e + end + + flushspecialrule = function(pos_h,pos_v,pos_r,width,height,depth,line,outline) + pdf_goto_pagemode() + + b = b + 1 ; buffer[b] = s_b + + local width = bpfactor * width + local height = bpfactor * height + local depth = bpfactor * depth + local total = height + depth + local line = bpfactor * line + local half = line / 2 + local rule + + if outline then + rule = f_f(line,half,-depth+half,width-line,total-line) + else + rule = f_b(line,-depth,width,total) + end + pdf_set_pos_temp(pos_h,pos_v) + + b = b + 1 ; buffer[b] = rule + b = b + 1 ; buffer[b] = s_e + end + +end + +--- basics + +local wrapup, registerpage do + + local pages = { } + local maxkids = 10 + local nofpages = 0 + local pagetag = "unset" + + registerpage = function(object) + nofpages = nofpages + 1 + local objnum = pdfpagereference(nofpages) + pages[nofpages] = { + page = nofpages, -- original number, only for diagnostics + objnum = objnum, + object = object, + tag = pagetag, + } + end + + function lpdf.setpagetag(tag) + pagetag = tag or "unset" + end + + function lpdf.getnofpages() + return nofpages + end + + function lpdf.getpagetags() + local list = { } + for i=1,nofpages do + list[i] = pages[i].tag + end + return list + end + + function lpdf.setpageorder(mapping) + -- mapping can be a hash so: + local list = table.sortedkeys(mapping) + local n = #list + if n == nofpages then + local done = { } + local hash = { } + for i=1,n do + local order = mapping[list[i]] + if hash[order] then + report("invalid page order, duplicate entry %i",order) + return + elseif order < 1 or order > nofpages then + report("invalid page order, no page %i",order) + return + else + done[i] = pages[order] + hash[order] = true + end + end + pages = done + else + report("invalid page order, %i entries expected",nofpages) + end + end + + -- We can have this, but then via codeinjections etc. Later. + + -- function structures.pages.swapthem() + -- local n = lpdf.getnofpages() + -- local t = { } + -- for i=1,n do + -- t[i] = i + -- end + -- for i=2,math.odd(n) and n or (n-1),2 do + -- t[i] = i+1 + -- t[i+1] = i + -- end + -- lpdf.setpageorder(t) + -- end + + wrapup = function(driver) + + -- hook (to reshuffle pages) + local pagetree = { } + local parent = nil + local minimum = 0 + local maximum = 0 + local current = 0 + if #pages > 1.5 * maxkids then + repeat + local plist, pnode + if current == 0 then + plist, minimum = pages, 1 + elseif current == 1 then + plist, minimum = pagetree, 1 + else + plist, minimum = pagetree, maximum + 1 + end + maximum = #plist + if maximum > minimum then + local kids + for i=minimum,maximum do + local p = plist[i] + if not pnode or #kids == maxkids then + kids = pdfarray() + parent = pdfreserveobject() + pnode = pdfdictionary { + objnum = parent, + Type = pdf_pages, + Kids = kids, + Count = 0, + } + pagetree[#pagetree+1] = pnode + end + kids[#kids+1] = pdfreference(p.objnum) + pnode.Count = pnode.Count + (p.Count or 1) + p.Parent = pdfreference(parent) + end + end + current = current + 1 + until maximum == minimum + -- flush page tree + for i=1,#pagetree do + local entry = pagetree[i] + local objnum = entry.objnum + entry.objnum = nil + pdfflushobject(objnum,entry) + end + else + -- ugly + local kids = pdfarray() + local list = pdfdictionary { + Type = pdf_pages, + Kids = kids, + Count = nofpages, + } + parent = pdfreserveobject() + for i=1,nofpages do + local page = pages[i] + kids[#kids+1] = pdfreference(page.objnum) + page.Parent = pdfreference(parent) + end + pdfflushobject(parent,list) + end + for i=1,nofpages do + local page = pages[i] + local object = page.object + object.Parent = page.Parent + pdfflushobject(page.objnum,object) + end + lpdf.addtocatalog("Pages",pdfreference(parent)) + + end + +end + +pdf_h, pdf_v = 0, 0 + +local function initialize(driver,details) + reset_variables(details) + reset_buffer() +end + +-- This will all move and be merged and become less messy. + +-- todo: more clever resource management: a bit tricky as we can inject +-- stuff in the page stream + +local compact = false + +do + + -- This is more a convenience feature and it might even be not entirely robust. + -- It removes redundant color directives which makes the page stream look a bit + -- nicer (also when figuring out issues). I might add more here but there is + -- some additional overhead involved so runtime can be impacted. + + local P, R, S, Cs, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.Cs, lpeg.match + + local p_ds = (R("09") + S(" ."))^1 + ----- p_nl = S("\n\r")^1 + local p_nl = S("\n")^1 + local p_eg = P("Q") + + local p_cl = p_ds * (P("rg") + P("g") + P("k")) * p_ds * (P("RG") + P("G") + P("K")) + ----- p_cl = (p_ds * (P("rg") + P("g") + P("k") + P("RG") + P("G") + P("K")))^1 + local p_tr = P("/Tr") * p_ds * P("gs") + + local p_no_cl = (p_cl * p_nl) / "" + local p_no_tr = (p_tr * p_nl) / "" + local p_no_nl = 1 - p_nl + + local p_do_cl = p_cl * p_nl + local p_do_tr = p_tr * p_nl + + local p_do_eg = p_eg * p_nl + + local pattern = Cs( ( + (p_no_cl + p_no_tr)^0 * p_do_eg -- transparencies and colors before Q + + p_no_tr * p_no_cl * p_do_tr * p_do_cl -- transparencies and colors before others + + p_no_cl * p_do_cl -- successive colors + + p_no_tr * p_do_tr -- successive transparencies + + p_no_nl^1 + + 1 + )^1 ) + + local oldsize = 0 + local newsize = 0 + + directives.register("pdf.compact", function(v) + compact = v and function(s) + oldsize = oldsize + #s + s = lpegmatch(pattern,s) or s + newsize = newsize + #s + return s + end + end) + + statistics.register("pdf pagestream",function() + if oldsize ~= newsize then + return string.format("old size: %i, new size %i",oldsize,newsize) + end + end) + + +end + +local flushdeferred -- defined later + +local level = 0 + +local finalize do + + local f_font = formatters["F%d"] + + local f_form = formatters["Fm%d"] + local f_group = formatters["Gp%d"] + local f_image = formatters["Im%d"] + + finalize = function(driver,details) + + level = level + 1 + + pdf_goto_pagemode() -- for now + + local objnum = details.objnum + local specification = details.specification + + local content = concat(buffer,"\n",1,b) + + if compact then + content = compact(content) + end + + local fonts = nil + local xforms = nil + + if next(usedfonts) then + fonts = pdfdictionary { } + for k, v in next, usedfonts do + fonts[f_font(v)] = pdfreference(pdfgetfontobjnumber(k)) -- we can overload for testing + end + end + + -- messy: use real indexes for both ... so we need to change some in the + -- full luatex part + + if next(usedxforms) or next(usedximages) or next(usedxgroups) then + xforms = pdfdictionary { } + for k in sortedhash(usedxforms) do + -- xforms[f_form(k)] = pdfreference(k) + xforms[f_form(getxformname(k))] = pdfreference(k) + end + for k, v in sortedhash(usedximages) do + xforms[f_image(k)] = pdfreference(v) + end + for k, v in sortedhash(usedxgroups) do + xforms[f_group(k)] = pdfreference(v) + end + end + + reset_buffer() + + -- finish_pdfpage_callback(shippingmode == "page") + + if shippingmode == "page" then + + local pageproperties = lpdf.getpageproperties() + + local pageresources = pageproperties.pageresources + local pageattributes = pageproperties.pageattributes + local pagesattributes = pageproperties.pagesattributes + + pageresources.Font = fonts + pageresources.XObject = xforms + pageresources.ProcSet = lpdf.procset() + + local xorigin, yorigin, relocated = backends.codeinjections.getpageorigin() -- for now here + + local bbox = pdfarray { + (boundingbox[1] + xorigin) * bpfactor, + (boundingbox[2] + yorigin) * bpfactor, + (boundingbox[3] + xorigin) * bpfactor, + (boundingbox[4] + yorigin) * bpfactor, + } + + if relocated then + content = formatters["1 0 0 1 %.6N %.6N cm\n%s"](bbox[1],bbox[2],content) + end + + local contentsobj = pdfflushstreamobject(content,false,false) + + pageattributes.Type = pdf_page + pageattributes.Contents = pdfreference(contentsobj) + pageattributes.Resources = pageresources + -- pageattributes.Resources = pdfreference(pdfflushobject(pageresources)) + -- pageattributes.MediaBox = bbox + pageattributes.MediaBox = pdfsharedobject(bbox) + pageattributes.Parent = nil -- precalculate + pageattributes.Group = nil -- todo + + -- resources can be indirect + + registerpage(pageattributes) + + lpdf.finalizepage(true) + + -- if relocated then + -- if pageattributes.TrimBox then pageattributes.TrimBox = box end + -- if pageattributes.CropBox then pageattributes.CropBox = box end + -- if pageattributes.BleedBox then pageattributes.BleedBox = box end + -- end + + if pageattributes.TrimBox then pageattributes.TrimBox = relocated and pdfsharedobject(box or pageattributes.TrimBox ) end + if pageattributes.CropBox then pageattributes.CropBox = relocated and pdfsharedobject(box or pageattributes.CropBox ) end + if pageattributes.BleedBox then pageattributes.BleedBox = relocated and pdfsharedobject(box or pageattributes.BleedBox) end + + else + + local xformtype = specification.type or 0 + local margin = specification.margin or 0 + local attributes = specification.attributes or "" + local resources = specification.resources or "" + + local wrapper = nil + + if xformtype == 0 then + wrapper = pdfdictionary { + Type = pdf_xobject, + Subtype = pdf_form, + FormType = 1, + BBox = nil, + Matrix = nil, + Resources = nil, + } + else + wrapper = pdfdictionary { + BBox = nil, + Matrix = nil, + Resources = nil, + } + end + if xformtype == 0 or xformtype == 1 or xformtype == 3 then + wrapper.BBox = pdfarray { + -margin * bpfactor, + -margin * bpfactor, + (boundingbox[3] + margin) * bpfactor, + (boundingbox[4] + margin) * bpfactor, + } + end + if xformtype == 0 or xformtype == 2 or xformtype == 3 then + -- can be shared too + wrapper.Matrix = pdfarray { 1, 0, 0, 1, 0, 0 } + end + + -- todo: additional = resources + + local boxresources = lpdf.collectedresources { serialize = false } + boxresources.Font = fonts + boxresources.XObject = xforms + + -- todo: maybe share them + -- wrapper.Resources = pdfreference(pdfflushobject(boxresources)) + + if resources ~= "" then + boxresources = boxresources + resources + end + if attributes ~= "" then + wrapper = wrapper + attributes + end + + wrapper.Resources = next(boxresources) and boxresources or nil + wrapper.ProcSet = lpdf.procset() + + -- pdfflushstreamobject(content,wrapper,false,objectnumber) + pdfflushstreamobject(content,wrapper,false,specification.objnum) + + end + + for objnum in sortedhash(usedxforms) do + local f = flushedxforms[objnum] + if f[1] == false then + f[1] = true + local objnum = f[2] -- specification.objnum + local specification = boxresources[objnum] + local list = specification.list + localconverter(list,"xform",f[2],specification) + end + end + + pdf_h, pdf_v = 0, 0 + + if level == 1 then + flushdeferred() + end + level = level - 1 + + end + +end + +updaters.register("backend.update.pdf",function() + job.positions.registerhandlers { + getpos = drivers.getpos, + getrpos = drivers.getrpos, + gethpos = drivers.gethpos, + getvpos = drivers.getvpos, + } +end) + +updaters.register("backend.update",function() + local saveboxresource = tex.boxresources.save + -- + -- also in lpdf-res .. brrr .. needs fixing + -- + backends.codeinjections.registerboxresource = function(n,offset) + local r = saveboxresource(n,nil,nil,false,0,offset or 0) + return r + end +end) + +-- now comes the pdf file handling + +local objects = { } +local streams = { } -- maybe just parallel to objects (no holes) +local nofobjects = 0 +local offset = 0 +local f = false +local flush = false +local threshold = 40 -- also #("/Filter /FlateDecode") (compression threshold) +local objectstream = true +local compress = true +local cache = false +local info = "" +local catalog = "" +local lastdeferred = false +local majorversion = 1 +local minorversion = 7 +local trailerid = true + +directives.register("backend.pdf.threshold",function(v) + if v then + threshold = tonumber(v) or 40 + else + threshold = -1000 + end +end) + +local f_object = formatters["%i 0 obj\010%s\010endobj\010"] +local f_stream_n_u = formatters["%i 0 obj\010<< /Length %i >>\010stream\010%s\010endstream\010endobj\010"] +local f_stream_n_c = formatters["%i 0 obj\010<< /Filter /FlateDecode /Length %i >>\010stream\010%s\010endstream\010endobj\010"] +local f_stream_d_u = formatters["%i 0 obj\010<< %s /Length %i >>\010stream\010%s\010endstream\010endobj\010"] +local f_stream_d_c = formatters["%i 0 obj\010<< %s /Filter /FlateDecode /Length %i >>\010stream\010%s\010endstream\010endobj\010"] +local f_stream_d_r = formatters["%i 0 obj\010<< %s >>\010stream\010%s\010endstream\010endobj\010"] + +----- f_object_b = formatters["%i 0 obj\010"] +local f_stream_b_n_u = formatters["%i 0 obj\010<< /Length %i >>\010stream\010"] +local f_stream_b_n_c = formatters["%i 0 obj\010<< /Filter /FlateDecode /Length %i >>\010stream\010"] +local f_stream_b_d_u = formatters["%i 0 obj\010<< %s /Length %i >>\010stream\010"] +local f_stream_b_d_c = formatters["%i 0 obj\010<< %s /Filter /FlateDecode /Length %i >>\010stream\010"] +local f_stream_b_d_r = formatters["%i 0 obj\010<< %s >>\010stream\010"] + +----- s_object_e = "\010endobj\010" +local s_stream_e = "\010endstream\010endobj\010" + +do + + local function setinfo() end -- we get it + local function setcatalog() end -- we get it + + local function settrailerid(v) + trailerid = v or false + end + + local function setmajorversion(v) majorversion = tonumber(v) or majorversion end + local function setminorversion(v) minorversion = tonumber(v) or minorversion end + + local function getmajorversion(v) return majorversion end + local function getminorversion(v) return minorversion end + + local function setcompresslevel (v) compress = v and v ~= 0 and true or false end + local function setobjcompresslevel(v) objectstream = v and v ~= 0 and true or false end + + local function getcompresslevel (v) return compress and 3 or 0 end + local function getobjcompresslevel(v) return objectstream and 1 or 0 end + + local function setpageresources () end -- needs to be sorted out + local function setpageattributes () end + local function setpagesattributes() end + + updaters.register("backend.update.pdf",function() + pdf.setinfo = setinfo + pdf.setcatalog = setcatalog + pdf.settrailerid = settrailerid + pdf.setmajorversion = setmajorversion + pdf.setminorversion = setminorversion + pdf.getmajorversion = getmajorversion + pdf.getminorversion = getminorversion + pdf.setcompresslevel = setcompresslevel + pdf.setobjcompresslevel = setobjcompresslevel + pdf.getcompresslevel = getcompresslevel + pdf.getobjcompresslevel = getobjcompresslevel + pdf.setpageresources = setpageresources + pdf.setpageattributes = setpageattributes + pdf.setpagesattributes = setpagesattributes + end) + +end + +local addtocache, flushcache, cache do + + local data, d = { }, 0 + local list, l = { }, 0 + local coffset = 0 + local indices = { } + + local maxsize = 32 * 1024 -- uncompressed + local maxcount = 0xFF + + addtocache = function(n,str) + local size = #str + if size == 0 then + -- todo: message + return + end + if coffset + size > maxsize or d == maxcount then + flushcache() + end + if d == 0 then + nofobjects = nofobjects + 1 + objects[nofobjects] = false + streams[nofobjects] = indices + cache = nofobjects + end + objects[n] = - cache + indices[n] = d + d = d + 1 + -- can have a comment n 0 obj as in luatex + data[d] = str + l = l + 1 ; list[l] = n + l = l + 1 ; list[l] = coffset + coffset = coffset + size + 1 + end + + local p_ObjStm = pdfconstant("ObjStm") + + flushcache = function() -- references cannot be stored + if l > 0 then + list = concat(list," ") + data[0] = list + data = concat(data,"\010",0,d) + local strobj = pdfdictionary { + Type = p_ObjStm, + N = d, + First = #list + 1, + } + objects[cache] = offset + local b = nil + local e = s_stream_e + if compress then + local comp = zlibcompress(data,3) + if comp and #comp < #data then + data = comp + b = f_stream_b_d_c(cache,strobj(),#data) + else + b = f_stream_b_d_u(cache,strobj(),#data) + end + else + b = f_stream_b_d_u(cache,strobj(),#data) + end + flush(f,b) + flush(f,data) + flush(f,e) + offset = offset + #b + #data + #e + data, d = { }, 0 + list, l = { }, 0 + coffset = 0 + indices = { } + end + end + +end + +local function pdfreserveobj() + nofobjects = nofobjects + 1 + objects[nofobjects] = false + return nofobjects +end + +local pages = table.setmetatableindex(function(t,k) + local v = pdfreserveobj() + t[k] = v + return v +end) + +local function getpageref(n) + return pages[n] +end + +local function refobj() + -- not needed, as we have auto-delay +end + +local function flushnormalobj(data,n) + if not n then + nofobjects = nofobjects + 1 + n = nofobjects + end + data = f_object(n,data) + if level == 0 then + objects[n] = offset + offset = offset + #data + flush(f,data) + else + if not lastdeferred then + lastdeferred = n + elseif n < lastdeferred then + lastdeferred = n + end + objects[n] = data + end + return n +end + +local function flushstreamobj(data,n,dict,comp,nolength) + if not data then + report("no data for %S",dict) + return + end + if not n then + nofobjects = nofobjects + 1 + n = nofobjects + end + local size = #data + if level == 0 then + local b = nil + local e = s_stream_e + if nolength then + b = f_stream_b_d_r(n,dict) + elseif comp ~= false and compress and size > threshold then + local compdata = zlibcompress(data,3) + if compdata then + local compsize = #compdata + if compsize > size - threshold then + b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size) + else + data = compdata + b = dict and f_stream_b_d_c(n,dict,compsize) or f_stream_b_n_c(n,compsize) + end + else + b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size) + end + else + b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size) + end + flush(f,b) + flush(f,data) + flush(f,e) + objects[n] = offset + offset = offset + #b + #data + #e + else + if nolength then + data = f_stream_d_r(n,dict,data) + elseif comp ~= false and compress and size > threshold then + local compdata = zlibcompress(data,3) + if compdata then + local compsize = #compdata + if compsize > size - threshold then + data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data) + else + data = dict and f_stream_d_c(n,dict,compsize,compdata) or f_stream_n_c(n,compsize,compdata) + end + else + data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data) + end + else + data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data) + end + if not lastdeferred then + lastdeferred = n + elseif n < lastdeferred then + lastdeferred = n + end + objects[n] = data + end + return n +end + +flushdeferred = function() -- was forward defined + if lastdeferred then + for n=lastdeferred,nofobjects do + local o = objects[n] + if type(o) == "string" then + objects[n] = offset + offset = offset + #o + flush(f,o) + end + end + lastdeferred = false + end +end + +-- n = pdf.obj([n,] objtext) +-- n = pdf.obj([n,] "file", filename) +-- n = pdf.obj([n,] "stream", streamtext [, attrtext]) +-- n = pdf.obj([n,] "streamfile", filename [, attrtext]) +-- +-- n = pdf.obj { +-- type = , -- raw|stream +-- immediate = , +-- objnum = , +-- attr = , +-- compresslevel = , +-- objcompression = , +-- file = , +-- string = , +-- nolength = , +-- } + +local function obj(a,b,c,d) + local kind --, immediate + local objnum, data, attr, filename + local compresslevel, objcompression, nolength + local argtype = type(a) + if argtype == "table" then + kind = a.type -- raw | stream + -- immediate = a.immediate + objnum = a.objnum + attr = a.attr + compresslevel = a.compresslevel + objcompression = a.objcompression + filename = a.file + data = a.string or a.stream or "" + nolength = a.nolength + if kind == "stream" then + if filename then + data = loaddata(filename) or "" + end + elseif kind == "raw"then + if filename then + data = loaddata(filename) or "" + end + elseif kind == "file"then + kind = "raw" + data = filename and loaddata(filename) or "" + elseif kind == "streamfile" then + kind = "stream" + data = filename and loaddata(filename) or "" + end + else + if argtype == "number" then + objnum = a + a, b, c = b, c, d + else + nofobjects = nofobjects + 1 + objnum = nofobjects + end + if b then + if a == "stream" then + kind = "stream" + data = b + elseif a == "file" then + -- kind = "raw" + data = loaddata(b) + elseif a == "streamfile" then + kind = "stream" + data = loaddata(b) + else + data = "" -- invalid object + end + attr = c + else + -- kind = "raw" + data = a + end + end + if not objnum then + nofobjects = nofobjects + 1 + objnum = nofobjects + end + -- todo: immediate + if kind == "stream" then + flushstreamobj(data,objnum,attr,compresslevel and compresslevel > 0 or nil,nolength) + elseif objectstream and objcompression ~= false then + addtocache(objnum,data) + else + flushnormalobj(data,objnum) + end + return objnum +end + +updaters.register("backend.update.pdf",function() + pdf.reserveobj = pdfreserveobj + pdf.getpageref = getpageref + pdf.refobj = refobj + pdf.flushstreamobj = flushstreamobj + pdf.flushnormalobj = flushnormalobj + pdf.obj = obj + pdf.immediateobj = obj +end) + +-- In lua 5.4 the methods are now moved one metalevel deeper so we need to get them +-- from mt.__index instead. (I did get that at first.) It makes for a slightly (imo) +-- nicer interface but no real gain in speed as we don't flush that often. + +local openfile, closefile do + + -- I used to do but then figured out that when I open and save a file in a mode + -- that removes trailing spaces, the xref becomes invalid. The problem was then that a + -- reconstruction of the file by a viewer gives weird effects probably because percent symbols + -- gets interpreted then. Thanks to Ross Moore for noticing this side effect! + + local f_used = formatters["%010i 00000 n\013\010"] + local f_link = formatters["%010i 00000 f\013\010"] + local f_first = formatters["%010i 65535 f\013\010"] + + local f_pdf = formatters["%%PDF-%i.%i\010"] + local f_xref = formatters["xref\0100 %i\010"] + local f_trailer_id = formatters["trailer\010<< %s /ID [ <%s> <%s> ] >>\010startxref\010%i\010%%%%EOF"] + local f_trailer_no = formatters["trailer\010<< %s >>\010startxref\010%i\010%%%%EOF"] + local f_startxref = formatters["startxref\010%i\010%%%%EOF"] + + local inmemory = false + local close = false + + -- local removefile = os.remove + + openfile = function(filename) + if inmemory then + local n = 0 + f = { } + flush = function(f,s) + n = n + 1 f[n] = s + end + close = function(f) + f = concat(f) + io.savedata(filename,f) + f = false + end + -- local n = 0 + -- f = { + -- write = function(self,s) + -- n = n + 1 f[n] = s + -- end, + -- close = function(self) + -- f = concat(f) + -- io.savedata(filename,f) + -- f = false + -- end, + -- } + else + f = io.open(filename,"wb") + if not f then + -- message + os.exit() + end + -- f:setvbuf("full",64*1024) + local m = getmetatable(f) + flush = m.write or m.__index.write + close = m.close or m.__index.close + end + -- + flush_buffer = function() + if b > 0 then + flush(f,concat(buffer,"",1,b)) + b = 0 + end + end + + local v = f_pdf(majorversion,minorversion) + -- local b = "%\xCC\xD5\xC1\xD4\xC5\xD8\xD0\xC4\xC6\010" -- LUATEXPDF (+128) + local b = "%\xC3\xCF\xCE\xD4\xC5\xD8\xD4\xD0\xC4\xC6\010" -- CONTEXTPDF (+128) + flush(f,v) + flush(f,b) + offset = #v + #b + end + + closefile = function(abort) + if abort then + f:close() + if not environment.arguments.nodummy then + f = io.open(abort,"wb") + if f then + local name = resolvers.findfile("context-lmtx-error.pdf") + if name then + local data = io.loaddata(name) + if data then + f:write(data) + f:close() + return + end + end + f:close() + end + end + os.remove(abort) + else + local xrefoffset = offset + local lastfree = 0 + local noffree = 0 + local catalog = lpdf.getcatalog() + local info = lpdf.getinfo() + if trailerid == true then + trailerid = md5HEX(osuuid()) + elseif trailerid and #trailerid > 32 then + trailerid = md5HEX(trailerid) + else + trailerid = false + end + if objectstream then + flushdeferred() + flushcache() + -- + xrefoffset = offset + -- + nofobjects = nofobjects + 1 + objects[nofobjects] = offset -- + 1 + -- + -- combine these three in one doesn't really give less code so + -- we go for the efficient ones + -- + local nofbytes = 4 + local c1, c2, c3, c4 + if offset <= 0xFFFF then + nofbytes = 2 + for i=1,nofobjects do + local o = objects[i] + if not o then + noffree = noffree + 1 + else + local strm = o < 0 + if strm then + o = -o + end + c1 = extract(o,8,8) + c2 = extract(o,0,8) + if strm then + objects[i] = char(2,c1,c2,streams[o][i]) + else + objects[i] = char(1,c1,c2,0) + end + end + end + if noffree > 0 then + for i=nofobjects,1,-1 do + local o = objects[i] + if not o then + local f1 = extract(lastfree,8,8) + local f2 = extract(lastfree,0,8) + objects[i] = char(0,f1,f2,0) + lastfree = i + end + end + end + elseif offset <= 0xFFFFFF then + nofbytes = 3 + for i=1,nofobjects do + local o = objects[i] + if not o then + noffree = noffree + 1 + else + local strm = o < 0 + if strm then + o = -o + end + c1 = extract(o,16,8) + c2 = extract(o, 8,8) + c3 = extract(o, 0,8) + if strm then + objects[i] = char(2,c1,c2,c3,streams[o][i]) + else + objects[i] = char(1,c1,c2,c3,0) + end + end + end + if noffree > 0 then + for i=nofobjects,1,-1 do + local o = objects[i] + if not o then + local f1 = extract(lastfree,16,8) + local f2 = extract(lastfree, 8,8) + local f3 = extract(lastfree, 0,8) + objects[i] = char(0,f1,f2,f3,0) + lastfree = i + end + end + end + else + nofbytes = 4 + for i=1,nofobjects do + local o = objects[i] + if not o then + noffree = noffree + 1 + else + local strm = o < 0 + if strm then + o = -o + end + c1 = extract(o,24,8) + c2 = extract(o,16,8) + c3 = extract(o, 8,8) + c4 = extract(o, 0,8) + if strm then + objects[i] = char(2,c1,c2,c3,c4,streams[o][i]) + else + objects[i] = char(1,c1,c2,c3,c4,0) + end + end + end + if noffree > 0 then + for i=nofobjects,1,-1 do + local o = objects[i] + if not o then + local f1 = extract(lastfree,24,8) + local f2 = extract(lastfree,16,8) + local f3 = extract(lastfree, 8,8) + local f4 = extract(lastfree, 0,8) + objects[i] = char(0,f1,f2,f3,f4,0) + lastfree = i + end + end + end + end + objects[0] = rep("\0",1+nofbytes+1) + local data = concat(objects,"",0,nofobjects) + local xref = pdfdictionary { + Type = pdfconstant("XRef"), + Size = nofobjects + 1, + W = pdfarray { 1, nofbytes, 1 }, + Root = catalog, + Info = info, + ID = trailerid and pdfarray { pdfliteral(trailerid,true), pdfliteral(trailerid,true) } or nil, + } + if compress then + local comp = zlibcompress(data,3) + if comp then + data = comp + flush(f,f_stream_b_d_c(nofobjects,xref(),#data)) + else + flush(f,f_stream_b_d_u(nofobjects,xref(),#data)) + end + else + flush(f,f_stream_b_d_u(nofobjects,xref(),#data)) + end + flush(f,data) + flush(f,s_stream_e) + flush(f,f_startxref(xrefoffset)) + else + flushdeferred() + xrefoffset = offset + flush(f,f_xref(nofobjects+1)) + local trailer = pdfdictionary { + Size = nofobjects+1, + Root = catalog, + Info = info, + } + for i=1,nofobjects do + local o = objects[i] + if o then + objects[i] = f_used(o) + end + end + for i=nofobjects,1,-1 do + local o = objects[i] + if not o then + objects[i] = f_link(lastfree) + lastfree = i + end + end + objects[0] = f_first(lastfree) + flush(f,concat(objects,"",0,nofobjects)) + trailer.Size = nofobjects + 1 + if trailerid then + flush(f,f_trailer_id(trailer(),trailerid,trailerid,xrefoffset)) + else + flush(f,f_trailer_no(trailer(),xrefoffset)) + end + end + f:close() + end + io.flush() + closefile = function() end + end + +end + +-- For the moment we overload it here, although back-fil.lua eventually will +-- be merged with back-pdf as it's pdf specific, or maybe back-imp-pdf or so. + +updaters.register("backend.update.pdf",function() + + -- We overload img but at some point it will even go away, so we just + -- reimplement what we need in context. This will change completely i.e. + -- we will drop the low level interface! + + local codeinjections = backends.pdf.codeinjections + + local imagetypes = images.types -- pdf png jpg jp2 jbig2 stream memstream + local img_none = imagetypes.none + + local rulecodes = nodes.rulecodes + + local setprop = nodes.nuts.setprop + + local report_images = logs.reporter("backend","images") + + local lastindex = 0 + local indices = { } + + local bpfactor = number.dimenfactors.bp + local imagerule_code = rulecodes.image + + function codeinjections.newimage(specification) + return specification + end + + function codeinjections.copyimage(original) + return setmetatableindex(original) + end + + function codeinjections.scanimgage(specification) + return specification + end + + local function embedimage(specification) + if specification then + lastindex = lastindex + 1 + index = lastindex + specification.index = index + local xobject = pdfdictionary { } + if not specification.notype then + xobject.Type = pdf_xobject + xobject.Subtype = pdf_form + xobject.FormType = 1 + end + local bbox = specification.bbox + if bbox and not specification.nobbox then + xobject.BBox = pdfarray { + bbox[1] * bpfactor, + bbox[2] * bpfactor, + bbox[3] * bpfactor, + bbox[4] * bpfactor, + } + end + xobject = xobject + specification.attr + if bbox and not specification.width then + specification.width = bbox[3] + end + if bbox and not specification.height then + specification.height = bbox[4] + end + local dict = xobject() + -- + nofobjects = nofobjects + 1 + local objnum = nofobjects + local nolength = specification.nolength + local stream = specification.stream or specification.string + -- + -- We cannot set type in native img so we need this hack or + -- otherwise we need to patch too much. Better that i write + -- a wrapper then. Anyway, it has to be done better: a key that + -- tells either or not to scale by xsize/ysize when flushing. + -- + if not specification.type then + local kind = specification.kind + if kind then + -- take that one + elseif attr and find(attr,"BBox") then + kind = img_stream + else + -- hack: a bitmap + kind = img_none + end + specification.type = kind + specification.kind = kind + end + local compress = compresslevel and compresslevel > 0 or nil + flushstreamobj(stream,objnum,dict,compress,nolength) + specification.objnum = objnum + specification.rotation = specification.rotation or 0 + specification.orientation = specification.orientation or 0 + specification.transform = specification.transform or 0 + specification.stream = nil + specification.attr = nil + specification.type = specification.kind or specification.type or img_none + indices[index] = specification -- better create a real specification + return specification + end + end + + codeinjections.embedimage = embedimage + + function codeinjections.wrapimage(specification) + -- + local index = specification.index + if not index then + embedimage(specification) + end + -- + local width = specification.width or 0 + local height = specification.height or 0 + local depth = specification.depth or 0 + -- newimagerule + local n = nodes.pool.rule(width,height,depth) + n.subtype = imagerule_code + setprop(tonut(n),"index",specification.index) + return n + end + + function pdf.includeimage(index) + local specification = indices[index] + if specification then + local bbox = specification.bbox + local xorigin = bbox[1] + local yorigin = bbox[2] + local xsize = bbox[3] - xorigin -- we need the original ones, not the 'rotated' ones + local ysize = bbox[4] - yorigin -- we need the original ones, not the 'rotated' ones + local transform = specification.transform or 0 + local objnum = specification.objnum or pdfreserveobj() + local groupref = nil + local kind = specification.kind or specification.type or img_none -- determines scaling type + return + kind, + xorigin, yorigin, + xsize, ysize, + transform, + objnum, + groupref + end + end + +end) + +updaters.register("backend.update.lpdf",function() + + -- todo: an md5 or sha2 hash can save space + -- todo: make a type 3 font instead + -- todo: move to lpdf namespace + + local pdfimage = lpdf.epdf.image + local newpdf = pdfimage.new + local openpdf = pdfimage.open + local closepdf = pdfimage.close + local copypage = pdfimage.copy + + local embedimage = images.embed + + local nofstreams = 0 + local topdf = { } + local toidx = { } + + local function storedata_s(pdf) + local idx = toidx[pdf] + if not idx then + nofstreams = nofstreams + 1 + idx = nofstreams + toidx[pdf] = nofstreams + topdf[idx] = pdf + end + return idx + end + + local function vfimage_s(id,wd,ht,dp,pos_h,pos_v) + local index = topdf[id] + if type(index) == "string" then + local pdfdoc = newpdf(index,#index) + local image = copypage(pdfdoc) + local bbox = image.bbox + image.width = bbox[3] - bbox[1] + image.height = bbox[4] - bbox[2] + embedimage(image) + index = image.index + topdf[id] = index + end + -- pdf.print or pdf.literal + flushimage(index,wd,ht,dp,pos_h,pos_v) + end + + local function storedata_n(name,page) + local idx = toidx[pdf] + if not idx then + nofstreams = nofstreams + 1 + idx = nofstreams + toidx[pdf] = nofstreams + topdf[idx] = pdf + end + return idx + end + + -- We need to have a way to close such a pdf ... esp for fonts. + + local pdfdocs = { } + + local function vfimage_n(name,page,wd,ht,dp,pos_h,pos_v) + local d = pdfdocs[name] + if not d then + d = { doc = openpdf(name), pages = { } } + pdfdocs[name] = d + end + local index = d.pages[page] + if not index then + local image = copypage(d.doc,page) + local bbox = image.bbox + image.width = bbox[3] - bbox[1] + image.height = bbox[4] - bbox[2] + embedimage(image) + index = image.index + d.pages[page] = index + end + flushimage(index,wd,ht,dp,pos_h,pos_v) + end + + local function pdfvfimage(wd,ht,dp,data,name) + if type(data) == "number" then + return { "lua", function(font,char,pos_h,pos_v) + vfimage_n(name,data,wd,ht,dp,pos_h,pos_v) + end } + else + return { "lua", function(font,char,pos_h,pos_v) + local id = storedata_s(data) + vfimage_s(id,wd,ht,dp,pos_h,pos_v) + end } + end + end + + lpdf.vfimage = pdfvfimage + +end) + +-- The driver. + +do + + -- local addsuffix = file.addsuffix + local texgetbox = tex.getbox + + local pdfname = nil + local converter = nil + local useddriver = nil -- a bit of a hack + + local function outputfilename(driver) + return pdfname + end + + -- todo: prevent twice + + local function prepare(driver) + if not environment.initex then + -- install new functions in pdf namespace + updaters.apply("backend.update.pdf") + -- install new functions in lpdf namespace + updaters.apply("backend.update.lpdf") + -- adapt existing shortcuts to lpdf namespace + updaters.apply("backend.update.tex") + -- adapt existing shortcuts to tex namespace + updaters.apply("backend.update") + -- + -- if rawget(pdf,"setforcefile") then + -- pdf.setforcefile(false) -- default anyway + -- end + -- + -- pdfname = file.addsuffix(tex.jobname,"pdf") + pdfname = tex.jobname .. ".pdf" + openfile(pdfname) + -- + luatex.registerstopactions(1,function() + if pdfname then + lpdf.finalizedocument() + closefile() + end + end) + -- + luatex.registerpageactions(1,function() + if pdfname then + lpdf.finalizepage(true) + end + end) + -- -- + lpdf.registerdocumentfinalizer(wrapup,nil,"wrapping up") + -- + end + -- + environment.lmtxmode = CONTEXTLMTXMODE + -- + converter = drivers.converters.lmtx + useddriver = driver + end + + local function wrapup(driver) + if pdfname then + closefile() + pdfname = nil + end + end + + local function cleanup(driver) + if pdfname then + closefile(pdfname) + pdfname = nil + end + end + + local function convert(driver,boxnumber) + converter(driver,texgetbox(boxnumber),"page") + end + + localconverter = function(...) + converter(useddriver,...) + end + + drivers.install { + name = "pdf", + flushers = { + character = flushcharacter, + fontchar = flushfontchar, + rule = flushrule, + simplerule = flushsimplerule, + specialrule = flushspecialrule, + pushorientation = pushorientation, + poporientation = poporientation, + -- + literal = flushliteral, + setmatrix = flushsetmatrix, + save = flushsave, + restore = flushrestore, + image = flushimage, + group = flushgroup, + -- + updatefontstate = updatefontstate, + }, + actions = { + prepare = prepare, + wrapup = wrapup, + cleanup = cleanup, + -- + initialize = initialize, + convert = convert, + finalize = finalize, + -- + outputfilename = outputfilename, + }, + } + +end diff --git a/tex/context/base/mkiv/lpdf-lmt.lua b/tex/context/base/mkiv/lpdf-lmt.lua deleted file mode 100644 index 5a1a6bc44..000000000 --- a/tex/context/base/mkiv/lpdf-lmt.lua +++ /dev/null @@ -1,2798 +0,0 @@ -if not modules then modules = { } end modules ['lpdf-lmt'] = { - version = 1.001, - optimize = true, - 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" -} - --- The code below was originally in back-lpd.lua but it makes more sense in --- this namespace. I will rename variables. --- --- There is no way that a lua based backend can compete with the original one --- for relative simple text runs. And we're talking seconds here on say 500 --- pages with paragraphs alternativng between three fonts and colors. But such --- documents are rare so in practice we are quite okay, especially because in --- ConTeXt we can gain quite a bit elsewhere. So, when we loose 30% on such --- simple documents, we break even on for instance the manual, and gain 30% on --- Thomas's turture test (also for other reasons). But .. who knows what magic --- I can cook up in due time. - --- If you consider this complex, watch: --- --- https://www.youtube.com/watch?v=6H-cAzfB2qo --- --- or in distractionmode: --- --- https://www.youtube.com/watch?v=TYuTE_1jvvE --- https://www.youtube.com/watch?v=nnicGKX3lvM --- --- For the moment we have to support the built in backend as well as the alternative. So --- the next interface is suboptimal and will change at some time. At that moment I will --- also optimize and extend. - -local type, next, unpack, tonumber = type, next, unpack, tonumber -local char, rep, find = string.char, string.rep, string.find -local formatters, splitupstring = string.formatters, string.splitup -local band, extract = bit32.band, bit32.extract -local concat, sortedhash = table.concat, table.sortedhash -local setmetatableindex = table.setmetatableindex -local loaddata = io.loaddata - -local bpfactor = number.dimenfactors.bp - -local md5HEX = md5.HEX -local osuuid = os.uuid -local zlibcompress = (xzip or zlib).compress - -local nuts = nodes.nuts -local tonut = nodes.tonut - -local getdata = nuts.getdata -local getsubtype = nuts.getsubtype -local getwhd = nuts.getwhd -local flushlist = nuts.flush_list - -local pdfincludeimage = lpdf.includeimage -local pdfgetfontname = lpdf.getfontname -local pdfgetfontobjnumber = lpdf.getfontobjnumber - -local pdfreserveobject = lpdf.reserveobject -local pdfpagereference = lpdf.pagereference -local pdfflushobject = lpdf.flushobject -local pdfreference = lpdf.reference -local pdfdictionary = lpdf.dictionary -local pdfarray = lpdf.array -local pdfconstant = lpdf.constant -local pdfflushstreamobject = lpdf.flushstreamobject -local pdfliteral = lpdf.literal -- not to be confused with a whatsit! - -local pdf_pages = pdfconstant("Pages") -local pdf_page = pdfconstant("Page") -local pdf_xobject = pdfconstant("XObject") -local pdf_form = pdfconstant("Form") - -local fonthashes = fonts.hashes -local characters = fonthashes.characters -local descriptions = fonthashes.descriptions -local parameters = fonthashes.parameters -local properties = fonthashes.properties - -local report = logs.reporter("backend") - --- used variables - -local pdf_h, pdf_v -local need_tm, need_tf, cur_tmrx, cur_factor, cur_f, cur_e -local need_width, need_mode, done_width, done_mode -local mode -local f_pdf_cur, f_pdf, fs_cur, fs, f_cur -local tj_delta, cw -local usedfonts, usedxforms, usedximages, usedxgroups -local getxformname, getximagename -local boundingbox, shippingmode, objectnumber -local tmrx, tmry, tmsx, tmsy, tmtx, tmty -local cmrx, cmry, cmsx, cmsy, cmtx, cmty - -local function usefont(t,k) -- a bit redundant hash - local v = pdfgetfontname(k) - t[k] = v - return v -end - -local function reset_variables(specification) - pdf_h, pdf_v = 0, 0 - cmrx, cmry = 1.0, 1.0 - cmsx, cmsy = 0.0, 0.0 - cmtx, cmty = 0.0, 0.0 - tmrx, tmry = 1.0, 1.0 - tmsx, tmsy = 0.0, 0.0 - tmtx, tmty = 0.0, 0.0 - need_tm = false - need_tf = false - need_width = 0 - need_mode = 0 - done_width = false - done_mode = false - mode = "page" - shippingmode = specification.shippingmode - objectnumber = specification.objectnumber - cur_tmrx = 0.0 - f_cur = 0 - f_pdf_cur = 0 -- nullfont - f_pdf = 0 -- nullfont - fs_cur = 0 - fs = 0 - cur_factor = 0 - cur_f = false - cur_e = false - tj_delta = 0.0 - cw = 0.0 - usedfonts = setmetatableindex(usefont) - usedxforms = { } - usedximages = { } - -- usedxgroups = { } - boundingbox = specification.boundingbox -end - --- buffer - -local buffer = lua.newtable(1024,0) -- { } -local b = 0 - -local function reset_buffer() - b = 0 -end - --- fonts - -local fontcharacters -local fontdescriptions -local fontparameters -local fontproperties -local usedcharacters = setmetatableindex("table") -local pdfcharacters - -local horizontalmode = true ------ widefontmode = true -local scalefactor = 1 -local threshold = 655360 -local tjfactor = 100 / 65536 - -lpdf.usedcharacters = usedcharacters - -local function updatefontstate(font) - fontcharacters = characters[font] - fontdescriptions = descriptions[font] - fontparameters = parameters[font] - fontproperties = properties[font] - local size = fontparameters.size -- or bad news - local designsize = fontparameters.designsize or size - pdfcharacters = usedcharacters[font] - horizontalmode = fontparameters.writingmode ~= "vertical" - -- widefontmode = fontproperties.encodingbytes == 2 - scalefactor = (designsize/size) * tjfactor - local fthreshold = fontproperties.threshold - threshold = (fthreshold and (size * fthreshold / 100)) or 655360 -end - --- helpers - -local f_cm = formatters["%.6N %.6N %.6N %.6N %.6N %.6N cm"] -local f_tm = formatters["%.6N %.6N %.6N %.6N %.6N %.6N Tm"] - -local saved_text_pos_v = 0 -local saved_text_pos_h = 0 - -local function begin_text() - saved_text_pos_h = pdf_h - saved_text_pos_v = pdf_v - b = b + 1 ; buffer[b] = "BT" - need_tf = true - need_width = 0 - need_mode = 0 - mode = "text" -end - -local function end_text() - if done_width then - b = b + 1 ; buffer[b] = "0 w" - done_width = false - end - if done_mode then - b = b + 1 ; buffer[b] = "0 Tr" - done_mode = false - end - b = b + 1 ; buffer[b] = "ET" - pdf_h = saved_text_pos_h - pdf_v = saved_text_pos_v - mode = "page" -end - -local saved_chararray_pos_h -local saved_chararray_pos_v - -local saved_b = 0 - -local function begin_chararray() - saved_chararray_pos_h = pdf_h - saved_chararray_pos_v = pdf_v - cw = horizontalmode and saved_chararray_pos_h or - saved_chararray_pos_v - tj_delta = 0 - saved_b = b - b = b + 1 ; buffer[b] = " [" - mode = "chararray" -end - -local function end_chararray() - b = b + 1 ; buffer[b] = "] TJ" - buffer[saved_b] = concat(buffer,"",saved_b,b) - b = saved_b - pdf_h = saved_chararray_pos_h - pdf_v = saved_chararray_pos_v - mode = "text" -end - -local function begin_charmode() - b = b + 1 ; buffer[b] = "<" - mode = "char" -end - -local function end_charmode() - b = b + 1 ; buffer[b] = ">" - mode = "chararray" -end - -local function calc_pdfpos(h,v) - -- mostly char - if mode == "page" then - cmtx = h - pdf_h - cmty = v - pdf_v - return h ~= pdf_h or v ~= pdf_v - elseif mode == "text" then - tmtx = h - saved_text_pos_h - tmty = v - saved_text_pos_v - return h ~= pdf_h or v ~= pdf_v - elseif horizontalmode then - tmty = v - saved_text_pos_v - tj_delta = cw - h - return tj_delta ~= 0 or v ~= pdf_v - else - tmtx = h - saved_text_pos_h - tj_delta = cw + v - return tj_delta ~= 0 or h ~= pdf_h - end -end - -local function pdf_set_pos(h,v) - local move = calc_pdfpos(h,v) - if move then - b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor) - pdf_h = pdf_h + cmtx - pdf_v = pdf_v + cmty - end -end - -local function pdf_reset_pos() - if mode == "page" then - cmtx = - pdf_h - cmty = - pdf_v - if pdf_h == 0 and pdf_v == 0 then - return - end - elseif mode == "text" then - tmtx = - saved_text_pos_h - tmty = - saved_text_pos_v - if pdf_h == 0 and pdf_v == 0 then - return - end - elseif horizontalmode then - tmty = - saved_text_pos_v - tj_delta = cw - if tj_delta == 0 and pdf_v == 0 then - return - end - else - tmtx = - saved_text_pos_h - tj_delta = cw - if tj_delta == 0 and pdf_h == 0 then - return - end - end - b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor) - pdf_h = pdf_h + cmtx - pdf_v = pdf_v + cmty -end - -local function pdf_set_pos_temp(h,v) - local move = calc_pdfpos(h,v) - if move then - b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor) - end -end - --- these dummy returns makes using them a bit faster - -local function pdf_end_string_nl() - if mode == "char" then - end_charmode() - return end_chararray() - elseif mode == "chararray" then - return end_chararray() - end -end - -local function pdf_goto_textmode() - if mode == "page" then - pdf_reset_pos() - return begin_text() - elseif mode ~= "text" then - if mode == "char" then - end_charmode() - return end_chararray() - else -- if mode == "chararray" then - return end_chararray() - end - end -end - -local function pdf_goto_pagemode() - if mode ~= "page" then - if mode == "char" then - end_charmode() - end_chararray() - return end_text() - elseif mode == "chararray" then - end_chararray() - return end_text() - elseif mode == "text" then - return end_text() - end - end -end - -local function pdf_goto_fontmode() - if mode == "char" then - end_charmode() - end_chararray() - end_text() - elseif mode == "chararray" then - end_chararray() - end_text() - elseif mode == "text" then - end_text() - end - pdf_reset_pos() - mode = "page" -end - --- characters - -local flushcharacter do - - local round = math.round - - -- across pages ... todo: clean up because we don't need to pass the font - -- as fontparameters already has checked / set it we can also have a variable - -- for it so - - local naturalwidth = nil - - -- local naturalwidths = setmetatableindex(function(t,font) - -- local d = descriptions[font] - -- local c = characters[font] - -- local f = parameters[font].hfactor - -- local v = setmetatableindex(function(t,char) - -- local w - -- local e = d and d[char] - -- if e then - -- w = e.width - -- if w then - -- w = w * f - -- end - -- end - -- if not w then - -- e = c[char] - -- if e then - -- w = e.width or 0 - -- end - -- end - -- if not w then - -- w = 0 - -- end - -- t[char] = w - -- return w - -- end) - -- t[font] = v - -- return v - -- end) - - local naturalwidths = setmetatableindex(function(t,font) - local d = descriptions[font] - local c = characters[font] - local f = parameters[font].hfactor - local v = setmetatableindex(function(t,char) - local w - local e = c[char] - if e then - w = e.width or 0 - end - if not w then - e = d and d[char] - if e then - w = e.width - if w then - w = w * f - end - end - end - if not w then - w = 0 - end - t[char] = w - return w - end) - t[font] = v - return v - end) - - local function setup_fontparameters(font,factor,f,e) - local slant = fontparameters.slantfactor or 0 - local extend = fontparameters.extendfactor or 1 - local squeeze = fontparameters.squeezefactor or 1 - local expand = 1 + factor / 1000000 - local format = fontproperties.format - if e then - extend = extend * e - end - tmrx = expand * extend - tmsy = slant - tmry = squeeze - need_width = fontparameters.width or 0 - need_mode = fontparameters.mode or 0 - f_cur = font - f_pdf = usedfonts[font] -- cache - cur_factor = factor - cur_f = f - cur_e = e - tj_delta = 0 - fs = fontparameters.size * bpfactor - if f then - fs = fs * f - end - -- kind of special: - if format == "opentype" or format == "type1" then - fs = fs * 1000 / fontparameters.units -- can we avoid this ? - end - -- - naturalwidth = naturalwidths[font] - end - - -- This only saves a little on hz because there we switch a lot of - -- instances. - - -- local lastslant, lastextend, lastsqueeze, lastformat, lastsize, lastwidth, lastmode, lastused, lastfont - - -- local function setup_fontparameters(font,factor,f,e) - -- if font ~= lastfont then - -- lastslant = fontparameters.slantfactor or 0 - -- lastextend = fontparameters.extendfactor or 1 - -- lastsqueeze = fontparameters.squeezefactor or 1 - -- lastformat = fontproperties.format - -- lastsize = fontparameters.size * bpfactor - -- if format == "opentype" or format == "type1" then - -- lastsize = lastsize * 1000 / fontparameters.units -- can we avoid this ? - -- end - -- lastwidth = fontparameters.width - -- lastmode = fontparameters.mode - -- lastused = usedfonts[font] -- cache - -- lastfont = font - -- end - -- local expand = 1 + factor / 1000000 - -- if e then - -- tmrx = expand * lastextend * e - -- else - -- tmrx = expand * lastextend - -- end - -- tmsy = lastslant - -- tmry = lastsqueeze - -- need_width = lastwidth - -- need_mode = lastmode - -- f_cur = lastfont - -- f_pdf = lastused - -- cur_factor = factor - -- cur_f = f - -- cur_e = e - -- tj_delta = 0 - -- if f then - -- fs = lastsize * f - -- else - -- fs = lastsize - -- end - -- end - - local f_width = formatters["%.6N w"] - local f_mode = formatters["%i Tr"] -- can be hash - local f_font = formatters["/F%i %.6N Tf"] -- can be hash - - local s_width = "0 w" - local s_mode = "0 Tr" - - local function set_font() - -- if need_width and need_width ~= 0 then - if need_width ~= 0 then - b = b + 1 ; buffer[b] = f_width(bpfactor * need_width / 1000) - done_width = true - elseif done_width then - b = b + 1 ; buffer[b] = s_width - done_width = false - end - -- if need_mode and need_mode ~= 0 then - if need_mode ~= 0 then - b = b + 1 ; buffer[b] = f_mode(need_mode) - done_mode = true - elseif done_mode then - b = b + 1 ; buffer[b] = s_mode - done_mode = false - end - b = b + 1 ; buffer[b] = f_font(f_pdf,fs) - f_pdf_cur = f_pdf - fs_cur = fs - need_tf = false - need_tm = true - end - - local function set_textmatrix(h,v) - local move = calc_pdfpos(h,v) - if need_tm or move then - b = b + 1 ; buffer[b] = f_tm(tmrx, tmsx, tmsy, tmry, tmtx*bpfactor, tmty*bpfactor) - pdf_h = saved_text_pos_h + tmtx - pdf_v = saved_text_pos_v + tmty - need_tm = false - end - cur_tmrx = tmrx - end - - local f_hex_4 = formatters["%04X"] - local f_hex_2 = formatters["%02X"] - - local h_hex_4 = setmetatableindex(function(t,k) -- we already have this somewhere - if k < 256 then -- maybe 512 - -- not sparse in this range - for i=0,255 do - t[i] = f_hex_4(i) - end - return t[k] - else - local v = f_hex_4(k) - t[k] = v - return v - end - end) - local h_hex_2 = setmetatableindex(function(t,k) -- we already have this somewhere - local v = k < 256 and f_hex_2(k) or "00" - t[k] = v - return v - end) - - local trace_threshold = false trackers.register("backends.pdf.threshold", function(v) trace_threshold = v end) - - flushcharacter = function(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) - if need_tf or font ~= f_cur or f_pdf ~= f_pdf_cur or fs ~= fs_cur or mode == "page" then - pdf_goto_textmode() - setup_fontparameters(font,factor,f,e) - set_font() - elseif cur_tmrx ~= tmrx or cur_factor ~= factor or cur_f ~= f or cur_e ~= e then - setup_fontparameters(font,factor,f,e) - need_tm = true - end - local move = calc_pdfpos(pos_h,pos_v) - - -- if trace_threshold then - -- report( - -- "font %i, char %C, factor %i, naturalwidth %p, move %l, tm %l, hpos %p, delta %p, threshold %p, cw %p", - -- font,char,factor,naturalwidth[char],move,need_tm,pos_h,tj_delta,threshold,cw - -- ) - -- end - - if move or need_tm then - if not need_tm then - if horizontalmode then - if (saved_text_pos_v + tmty) ~= pdf_v then - need_tm = true - elseif tj_delta >= threshold or tj_delta <= -threshold then - need_tm = true - end - else - if (saved_text_pos_h + tmtx) ~= pdf_h then - need_tm = true - elseif tj_delta >= threshold or tj_delta <= -threshold then - need_tm = true - end - end - end - if need_tm then - pdf_goto_textmode() - set_textmatrix(pos_h,pos_v) - begin_chararray() - move = calc_pdfpos(pos_h,pos_v) - end - if move then - local d = tj_delta * scalefactor - if d <= -0.5 or d >= 0.5 then - if mode == "char" then - end_charmode() - end - b = b + 1 ; buffer[b] = round(d) -- or f_skip(d) - end - cw = cw - tj_delta - end - end - - if mode == "chararray" then - begin_charmode() - end - - cw = cw + naturalwidth[char] * tmrx - - local index = data.index or char - - b = b + 1 ; buffer[b] = font > 0 and h_hex_4[index] or h_hex_2[index] - - if not pdfcharacters[index] then - pdfcharacters[index] = true - end - - end - - flushfontchar = function(font,char,data) - local dummy = usedfonts[font] - local index = data.index or char - if not pdfcharacters[index] then - pdfcharacters[index] = true - end - return dummy - end - -end - --- literals - -local flushliteral do - - local nodeproperties = nodes.properties.data - local literalvalues = nodes.literalvalues - - local originliteral_code = literalvalues.origin - local pageliteral_code = literalvalues.page - local alwaysliteral_code = literalvalues.always - local rawliteral_code = literalvalues.raw - local textliteral_code = literalvalues.text - local fontliteral_code = literalvalues.font - - flushliteral = function(current,pos_h,pos_v,mode,str) - if mode then - if not str then - mode, str = originliteral_code, mode - elseif mode == "mode" then - mode = literalvalues[str] - if mode == originliteral_code then - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - elseif mode == pageliteral_code then - pdf_goto_pagemode() - elseif mode == textliteral_code then - pdf_goto_textmode() - elseif mode == fontliteral_code then - pdf_goto_fontmode() - elseif mode == alwaysliteral_code then - pdf_end_string_nl() - need_tm = true - elseif mode == rawliteral_code then - pdf_end_string_nl() - end - return - else - mode = literalvalues[mode] - end - else - local p = nodeproperties[current] - if p then - str = p.data - mode = p.mode - else - str, mode = getdata(current) - end - end - if str and str ~= "" then - if mode == originliteral_code then - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - elseif mode == pageliteral_code then - pdf_goto_pagemode() - elseif mode == textliteral_code then - pdf_goto_textmode() - elseif mode == fontliteral_code then - pdf_goto_fontmode() - elseif mode == alwaysliteral_code then - pdf_end_string_nl() - need_tm = true - elseif mode == rawliteral_code then - pdf_end_string_nl() - else - report("check literal") - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - end - b = b + 1 ; buffer[b] = str - end - end - - updaters.register("backend.update.pdf",function() - function pdf.print(mode,str) - if str then - mode = literalvalues[mode] - else - mode, str = originliteral_code, mode - end - if str and str ~= "" then - if mode == originliteral_code then - pdf_goto_pagemode() - -- pdf_set_pos(pdf_h,pdf_v) - elseif mode == pageliteral_code then - pdf_goto_pagemode() - elseif mode == textliteral_code then - pdf_goto_textmode() - elseif mode == fontliteral_code then - pdf_goto_fontmode() - elseif mode == alwaysliteral_code then - pdf_end_string_nl() - need_tm = true - elseif mode == rawliteral_code then - pdf_end_string_nl() - else - pdf_goto_pagemode() - -- pdf_set_pos(pdf_h,pdf_v) - end - b = b + 1 ; buffer[b] = str - end - end - end) - -end - --- grouping & orientation - -local flushsave, flushrestore, flushsetmatrix do - - local matrices = { } - local positions = { } - local nofpositions = 0 - local nofmatrices = 0 - - local f_matrix = formatters["%s 0 0 cm"] - - flushsave = function(current,pos_h,pos_v) - nofpositions = nofpositions + 1 - positions[nofpositions] = { pos_h, pos_v, nofmatrices } - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - b = b + 1 ; buffer[b] = "q" - end - - flushrestore = function(current,pos_h,pos_v) - if nofpositions < 1 then - return - end - local t = positions[nofpositions] - -- local h = pos_h - t[1] - -- local v = pos_v - t[2] - if shippingmode == "page" then - nofmatrices = t[3] - end - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - b = b + 1 ; buffer[b] = "Q" - nofpositions = nofpositions - 1 - end - - local function pdf_set_matrix(str,pos_h,pos_v) - if shippingmode == "page" then - local rx, sx, sy, ry = splitupstring(str," ") - if rx and ry and sx and ry then - rx, sx, sy, ry = tonumber(rx), tonumber(sx), tonumber(sy), tonumber(ry) - local tx = pos_h * (1 - rx) - pos_v * sy - local ty = pos_v * (1 - ry) - pos_h * sx - if nofmatrices > 0 then - local t = matrices[nofmatrices] - local r_x, s_x, s_y, r_y, te, tf = t[1], t[2], t[3], t[4], t[5], t[6] - rx, sx = rx * r_x + sx * s_y, rx * s_x + sx * r_y - sy, ry = sy * r_x + ry * s_y, sy * s_x + ry * r_y - tx, ty = tx * r_x + ty * s_y, tx * s_x + ty * r_y - end - nofmatrices = nofmatrices + 1 - matrices[nofmatrices] = { rx, sx, sy, ry, tx, ty } - end - end - end - - local nodeproperties = nodes.properties.data - - flushsetmatrix = function(current,pos_h,pos_v) - local str - if type(current) == "string" then - str = current - else - local p = nodeproperties[current] - if p then - str = p.matrix - else - str = getdata(current) -- for the moment - end - end - if str and str ~= "" then - pdf_set_matrix(str,pos_h,pos_v) - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - b = b + 1 ; buffer[b] = f_matrix(str) - end - end - - do - - local function hasmatrix() - return nofmatrices > 0 - end - - local function getmatrix() - if nofmatrices > 0 then - return unpack(matrices[nofmatrices]) - else - return 1, 0, 0, 1, 0, 0 - end - end - - updaters.register("backend.update.pdf",function() - pdf.hasmatrix = hasmatrix - pdf.getmatrix = getmatrix - end) - - end - - pushorientation = function(orientation,pos_h,pos_v,pos_r) - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - b = b + 1 ; buffer[b] = "q" - if orientation == 1 then - b = b + 1 ; buffer[b] = "0 -1 1 0 0 0 cm" -- 90 - elseif orientation == 2 then - b = b + 1 ; buffer[b] = "-1 0 0 -1 0 0 cm" -- 180 - elseif orientation == 3 then - b = b + 1 ; buffer[b] = "0 1 -1 0 0 0 cm" -- 270 - end - end - - poporientation = function(orientation,pos_h,pos_v,pos_r) - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - b = b + 1 ; buffer[b] = "Q" - end - - -- pushorientation = function(orientation,pos_h,pos_v,pos_r) - -- flushsave(false,pos_h,pos_v) - -- if orientation == 1 then - -- flushsetmatrix("0 -1 1 0",pos_h,pos_v) - -- elseif orientation == 2 then - -- flushsetmatrix("-1 0 0 -1",pos_h,pos_v) - -- elseif orientation == 3 then - -- flushsetmatrix("0 1 -1 0",pos_h,pos_v) - -- end - -- end - - -- poporientation = function(orientation,pos_h,pos_v,pos_r) - -- flushrestore(false,pos_h,pos_v) - -- end - -end - --- rules - -local flushedxforms = { } -- actually box resources but can also be direct -local localconverter = nil -- will be set - -local flushrule, flushsimplerule, flushimage, flushgroup do - - local rulecodes = nodes.rulecodes - local newrule = nodes.pool.rule - - local setprop = nuts.setprop - local getprop = nuts.getprop - - local normalrule_code = rulecodes.normal - local boxrule_code = rulecodes.box - local imagerule_code = rulecodes.image - local emptyrule_code = rulecodes.empty - local userrule_code = rulecodes.user - local overrule_code = rulecodes.over - local underrule_code = rulecodes.under - local fractionrule_code = rulecodes.fraction - local radicalrule_code = rulecodes.radical - local outlinerule_code = rulecodes.outline - - local rule_callback = callbacks.functions.process_rule - - local f_fm = formatters["/Fm%d Do"] - local f_im = formatters["/Im%d Do"] - local f_gr = formatters["/Gp%d Do"] - - local s_b = "q" - local s_e = "Q" - - local f_v = formatters["[] 0 d 0 J %.6N w 0 0 m %.6N 0 l S"] - local f_h = formatters["[] 0 d 0 J %.6N w 0 0 m 0 %.6N l S"] - - local f_f = formatters["0 0 %.6N %.6N re f"] - local f_o = formatters["[] 0 d 0 J 0 0 %.6N %.6N re S"] - local f_w = formatters["[] 0 d 0 J %.6N w 0 0 %.6N %.6N re S"] - - -- Historically the index is an object which is kind of bad. - - local boxresources, n = { }, 0 - - getxformname = function(index) - local l = boxresources[index] - if l then - return l.name - else - report("no box resource %S",index) - end - end - - updaters.register("backend.update.pdf",function() - pdf.getxformname = getxformname - end) - - local function saveboxresource(box,attributes,resources,immediate,kind,margin) - n = n + 1 - local immediate = true - local margin = margin or 0 -- or dimension - local objnum = pdfreserveobject() - local list = tonut(type(box) == "number" and tex.takebox(box) or box) - -- - local width, height, depth = getwhd(list) - -- - local l = { - width = width, - height = height, - depth = depth, - margin = margin, - attributes = attributes, - resources = resources, - list = nil, - type = kind, - name = n, - index = objnum, - objnum = objnum, - } - boxresources[objnum] = l - if immediate then - localconverter(list,"xform",objnum,l) - flushedxforms[objnum] = { true , objnum } - flushlist(list) - else - l.list = list - end - return objnum - end - - local function useboxresource(index,wd,ht,dp) - local l = boxresources[index] - if l then - if wd or ht or dp then - wd, ht, dp = wd or 0, ht or 0, dp or 0 - else - wd, ht, dp = l.width, l.height, l.depth - end - local rule = newrule(wd,ht,dp) -- newboxrule - rule.subtype = boxrule_code - setprop(tonut(rule),"index",index) - return rule, wd, ht, dp - else - report("no box resource %S",index) - end - end - - local function getboxresourcedimensions(index) - local l = boxresources[index] - if l then - return l.width, l.height, l.depth, l.margin - else - report("no box resource %S",index) - end - end - - local function getboxresourcebox(index) - local l = boxresources[index] - if l then - return l.list - end - end - - updaters.register("backend.update.tex",function() - tex.saveboxresource = saveboxresource - tex.useboxresource = useboxresource - tex.getboxresourcedimensions = getboxresourcedimensions - tex.getboxresourcebox = getboxresourcebox - end) - - -- a bit of a mess: index is now objnum but that has to change to a proper index - -- ... an engine inheritance - - local function flushpdfxform(current,pos_h,pos_v,pos_r,size_h,size_v) - -- object properties - local objnum = getprop(current,"index") - local name = getxformname(objnum) - local info = flushedxforms[objnum] - local r = boxresources[objnum] - if not info then - info = { false , objnum } - flushedxforms[objnum] = info - end - local wd, ht, dp = getboxresourcedimensions(objnum) - -- or: wd, ht, dp = r.width, r.height, r.depth - -- sanity check - local htdp = ht + dp - if wd == 0 or size_h == 0 or htdp == 0 or size_v == 0 then - return - end - -- calculate scale - local rx, ry = 1, 1 - if wd ~= size_h or htdp ~= size_v then - rx = size_h / wd - ry = size_v / htdp - end - -- flush the reference - usedxforms[objnum] = true - pdf_goto_pagemode() - calc_pdfpos(pos_h,pos_v) - tx = cmtx * bpfactor - ty = cmty * bpfactor - b = b + 1 ; buffer[b] = s_b - b = b + 1 ; buffer[b] = f_cm(rx,0,0,ry,tx,ty) - b = b + 1 ; buffer[b] = f_fm(name) - b = b + 1 ; buffer[b] = s_e - end - - -- place image also used in vf but we can use a different one if we need it - - local imagetypes = images.types -- pdf png jpg jp2 jbig2 stream memstream - local img_none = imagetypes.none - local img_pdf = imagetypes.pdf - local img_stream = imagetypes.stream - local img_memstream = imagetypes.memstream - - local one_bp = 65536 * bpfactor - - local imageresources, n = { }, 0 - - getximagename = function(index) - local l = imageresources[index] - if l then - return l.name - else - report("no image resource %S",index) - end - end - - updaters.register("backend.update.pdf",function() - pdf.getximagename = getximagename - end) - - -- Groups are flushed immediately but we can decide to make them into a - -- specific whatsit ... but not now. We could hash them if needed when - -- we use lot sof them in mp ... but not now. - - usedxgroups = { } - local groups = 0 - local group = nil - - flushgroup = function(content,bbox) - if not group then - group = pdfdictionary { - Type = pdfconstant("Group"), - S = pdfconstant("Transparency"), - } - end - local wrapper = pdfdictionary { - Type = pdf_xobject, - Subtype = pdf_form, - FormType = 1, - Group = group, - BBox = pdfarray(bbox), - Resources = lpdf.collectedresources { serialize = false }, - } - local objnum = pdfflushstreamobject(content,wrapper,false) - groups = groups + 1 - usedxgroups[groups] = objnum - return f_gr(groups) - end - - lpdf.flushgroup = flushgroup -- todo: access via driver in mlib-pps - - -- end of experiment - - local function flushpdfximage(current,pos_h,pos_v,pos_r,size_h,size_v) - - local width, - height, - depth = getwhd(current) - local total = height + depth - local transform = getprop(current,"transform") or 0 -- we never set it ... so just use rotation then - local index = getprop(current,"index") or 0 - local kind, - xorigin, - yorigin, - xsize, - ysize, - rotation, -- transform / orientation / rotation : it's a mess (i need to redo this) - objnum, - groupref = pdfincludeimage(index) -- needs to be sorted out, bad name (no longer mixed anyway) - - if not kind then - report("invalid image %S",index) - return - end - - local rx, sx, sy, ry, tx, ty = 1, 0, 0, 1, 0, 0 - - -- tricky: xsize and ysize swapped - - if kind == img_pdf or kind == img_stream or kind == img_memstream then - rx, ry, tx, ty = 1/xsize, 1/ysize, xorigin/xsize, yorigin/ysize - else - -- if kind == img_png then - -- -- if groupref > 0 and img_page_group_val == 0 then - -- -- img_page_group_val = groupref - -- -- end - -- end - rx, ry = bpfactor, bpfactor - end - - if band(transform,7) > 3 then - -- mirror - rx, tx = -rx, -tx - end - local t = band(transform + rotation,3) - if t == 0 then - -- nothing - elseif t == 1 then - -- rotation over 90 degrees (counterclockwise) - rx, sx, sy, ry, tx, ty = 0, rx, -ry, 0, -ty, tx - elseif t == 2 then - -- rotation over 180 degrees (counterclockwise) - rx, ry, tx, ty = -rx, -ry, -tx, -ty - elseif t == 3 then - -- rotation over 270 degrees (counterclockwise) - rx, sx, sy, ry, tx, ty = 0, -rx, ry, 0, ty, -tx - end - - rx = rx * width - sx = sx * total - sy = sy * width - ry = ry * total - tx = pos_h - tx * width - ty = pos_v - ty * total - - local t = transform + rotation - - if band(transform,7) > 3 then - t = t + 1 - end - - t = band(t,3) - - if t == 0 then - -- no transform - elseif t == 1 then - -- rotation over 90 degrees (counterclockwise) - tx = tx + width - elseif t == 2 then - -- rotation over 180 degrees (counterclockwise) - tx = tx + width - ty = ty + total - elseif t == 3 then - -- rotation over 270 degrees (counterclockwise) - ty = ty + total - end - - -- a flaw in original, can go: - -- - -- if img_page_group_val == 0 then - -- img_page_group_val = group_ref - -- end - - usedximages[index] = objnum -- hm - - pdf_goto_pagemode() - - calc_pdfpos(tx,ty) - - tx = cmtx * bpfactor - ty = cmty * bpfactor - - b = b + 1 ; buffer[b] = s_b - b = b + 1 ; buffer[b] = f_cm(rx,sx,sy,ry,tx,ty) - b = b + 1 ; buffer[b] = f_im(index) - b = b + 1 ; buffer[b] = s_e - end - - flushimage = function(index,width,height,depth,pos_h,pos_v) - - -- used in vf characters - - local total = height + depth - local kind, - xorigin, yorigin, - xsize, ysize, - rotation, - objnum, - groupref = pdfincludeimage(index) - - local rx = width / xsize - local sx = 0 - local sy = 0 - local ry = total / ysize - local tx = pos_h - -- to be sorted out - -- local ty = pos_v - depth - local ty = pos_v -- we assume that depth is dealt with in the caller (for now) - - usedximages[index] = objnum - - pdf_goto_pagemode() - - calc_pdfpos(tx,ty) - - tx = cmtx * bpfactor - ty = cmty * bpfactor - - b = b + 1 ; buffer[b] = s_b - b = b + 1 ; buffer[b] = f_cm(rx,sx,sy,ry,tx,ty) - b = b + 1 ; buffer[b] = f_im(index) - b = b + 1 ; buffer[b] = s_e - end - - -- For the moment we need this hack because the engine checks the 'image' - -- command in virtual fonts (so we use lua instead). - - flushrule = function(current,pos_h,pos_v,pos_r,size_h,size_v,subtype) - - if subtype == emptyrule_code then - return - elseif subtype == boxrule_code then - return flushpdfxform(current,pos_h,pos_v,pos_r,size_h,size_v) - elseif subtype == imagerule_code then - return flushpdfximage(current,pos_h,pos_v,pos_r,size_h,size_v) - end - if subtype == userrule_code or subtype >= overrule_code and subtype <= radicalrule_code then - pdf_goto_pagemode() - b = b + 1 ; buffer[b] = s_b - pdf_set_pos_temp(pos_h,pos_v) - rule_callback(current,size_h,size_v,pos_r) -- so we pass direction - b = b + 1 ; buffer[b] = s_e - return - end - - pdf_goto_pagemode() - - -- local saved_b = b - - b = b + 1 ; buffer[b] = s_b - - local dim_h = size_h * bpfactor - local dim_v = size_v * bpfactor - local rule - - if dim_v <= one_bp then - pdf_set_pos_temp(pos_h,pos_v + 0.5 * size_v) - rule = f_v(dim_v,dim_h) - elseif dim_h <= one_bp then - pdf_set_pos_temp(pos_h + 0.5 * size_h,pos_v) - rule = f_h(dim_h,dim_v) - else - pdf_set_pos_temp(pos_h,pos_v) - if subtype == outlinerule_code then - local linewidth = getdata(current) - if linewidth > 0 then - rule = f_w(linewidth * bpfactor,dim_h,dim_v) - else - rule = f_o(dim_h,dim_v) - end - else - rule = f_f(dim_h,dim_v) - end - end - - b = b + 1 ; buffer[b] = rule - b = b + 1 ; buffer[b] = s_e - - -- buffer[saved_b] = concat(buffer," ",saved_b,b) - -- b = saved_b - - end - - flushsimplerule = function(pos_h,pos_v,pos_r,size_h,size_v) - pdf_goto_pagemode() - - b = b + 1 ; buffer[b] = s_b - - local dim_h = size_h * bpfactor - local dim_v = size_v * bpfactor - local rule - - if dim_v <= one_bp then - pdf_set_pos_temp(pos_h,pos_v + 0.5 * size_v) - rule = f_v(dim_v,dim_h) - elseif dim_h <= one_bp then - pdf_set_pos_temp(pos_h + 0.5 * size_h,pos_v) - rule = f_h(dim_h,dim_v) - else - pdf_set_pos_temp(pos_h,pos_v) - rule = f_f(dim_h,dim_v) - end - - b = b + 1 ; buffer[b] = rule - b = b + 1 ; buffer[b] = s_e - end - -end - ---- basics - -local wrapup, registerpage do - - local pages = { } - local maxkids = 10 - local nofpages = 0 - local pagetag = "unset" - - registerpage = function(object) - nofpages = nofpages + 1 - local objnum = pdfpagereference(nofpages) - pages[nofpages] = { - page = nofpages, -- original number, only for diagnostics - objnum = objnum, - object = object, - tag = pagetag, - } - end - - function lpdf.setpagetag(tag) - pagetag = tag or "unset" - end - - function lpdf.getnofpages() - return nofpages - end - - function lpdf.getpagetags() - local list = { } - for i=1,nofpages do - list[i] = pages[i].tag - end - return list - end - - function lpdf.setpageorder(mapping) - -- mapping can be a hash so: - local list = table.sortedkeys(mapping) - local n = #list - if n == nofpages then - local done = { } - local hash = { } - for i=1,n do - local order = mapping[list[i]] - if hash[order] then - report("invalid page order, duplicate entry %i",order) - return - elseif order < 1 or order > nofpages then - report("invalid page order, no page %i",order) - return - else - done[i] = pages[order] - hash[order] = true - end - end - pages = done - else - report("invalid page order, %i entries expected",nofpages) - end - end - - -- We can have this, but then via codeinjections etc. Later. - - -- function structures.pages.swapthem() - -- local n = lpdf.getnofpages() - -- local t = { } - -- for i=1,n do - -- t[i] = i - -- end - -- for i=2,math.odd(n) and n or (n-1),2 do - -- t[i] = i+1 - -- t[i+1] = i - -- end - -- lpdf.setpageorder(t) - -- end - - wrapup = function(driver) - - -- hook (to reshuffle pages) - local pagetree = { } - local parent = nil - local minimum = 0 - local maximum = 0 - local current = 0 - if #pages > 1.5 * maxkids then - repeat - local plist, pnode - if current == 0 then - plist, minimum = pages, 1 - elseif current == 1 then - plist, minimum = pagetree, 1 - else - plist, minimum = pagetree, maximum + 1 - end - maximum = #plist - if maximum > minimum then - local kids - for i=minimum,maximum do - local p = plist[i] - if not pnode or #kids == maxkids then - kids = pdfarray() - parent = pdfreserveobject() - pnode = pdfdictionary { - objnum = parent, - Type = pdf_pages, - Kids = kids, - Count = 0, - } - pagetree[#pagetree+1] = pnode - end - kids[#kids+1] = pdfreference(p.objnum) - pnode.Count = pnode.Count + (p.Count or 1) - p.Parent = pdfreference(parent) - end - end - current = current + 1 - until maximum == minimum - -- flush page tree - for i=1,#pagetree do - local entry = pagetree[i] - local objnum = entry.objnum - entry.objnum = nil - pdfflushobject(objnum,entry) - end - else - -- ugly - local kids = pdfarray() - local list = pdfdictionary { - Type = pdf_pages, - Kids = kids, - Count = nofpages, - } - parent = pdfreserveobject() - for i=1,nofpages do - local page = pages[i] - kids[#kids+1] = pdfreference(page.objnum) - page.Parent = pdfreference(parent) - end - pdfflushobject(parent,list) - end - for i=1,nofpages do - local page = pages[i] - local object = page.object - object.Parent = page.Parent - pdfflushobject(page.objnum,object) - end - lpdf.addtocatalog("Pages",pdfreference(parent)) - - end - -end - -pdf_h, pdf_v = 0, 0 - -local function initialize(driver,details) - reset_variables(details) - reset_buffer() -end - --- This will all move and be merged and become less messy. - --- todo: more clever resource management: a bit tricky as we can inject --- stuff in the page stream - -local compact = false - -do - - -- This is more a convenience feature and it might even be not entirely robust. - -- It removes redundant color directives which makes the page stream look a bit - -- nicer (also when figuring out issues). I might add more here but there is - -- some additional overhead involved so runtime can be impacted. - - local P, R, S, Cs, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.Cs, lpeg.match - - local p_ds = (R("09") + S(" ."))^1 - ----- p_nl = S("\n\r")^1 - local p_nl = S("\n")^1 - local p_eg = P("Q") - - local p_cl = p_ds * (P("rg") + P("g") + P("k")) * p_ds * (P("RG") + P("G") + P("K")) - ----- p_cl = (p_ds * (P("rg") + P("g") + P("k") + P("RG") + P("G") + P("K")))^1 - local p_tr = P("/Tr") * p_ds * P("gs") - - local p_no_cl = (p_cl * p_nl) / "" - local p_no_tr = (p_tr * p_nl) / "" - local p_no_nl = 1 - p_nl - - local p_do_cl = p_cl * p_nl - local p_do_tr = p_tr * p_nl - - local p_do_eg = p_eg * p_nl - - local pattern = Cs( ( - (p_no_cl + p_no_tr)^0 * p_do_eg -- transparencies and colors before Q - + p_no_tr * p_no_cl * p_do_tr * p_do_cl -- transparencies and colors before others - + p_no_cl * p_do_cl -- successive colors - + p_no_tr * p_do_tr -- successive transparencies - + p_no_nl^1 - + 1 - )^1 ) - - local oldsize = 0 - local newsize = 0 - - directives.register("pdf.compact", function(v) - compact = v and function(s) - oldsize = oldsize + #s - s = lpegmatch(pattern,s) or s - newsize = newsize + #s - return s - end - end) - - statistics.register("pdf pagestream",function() - if oldsize ~= newsize then - return string.format("old size: %i, new size %i",oldsize,newsize) - end - end) - - -end - -local flushdeferred -- defined later - -local level = 0 - -local finalize do - - local f_font = formatters["F%d"] - - local f_form = formatters["Fm%d"] - local f_group = formatters["Gp%d"] - local f_image = formatters["Im%d"] - - finalize = function(driver,details) - - level = level + 1 - - pdf_goto_pagemode() -- for now - - local objnum = details.objnum - local specification = details.specification - - local content = concat(buffer,"\n",1,b) - - if compact then - content = compact(content) - end - - local fonts = nil - local xforms = nil - - if next(usedfonts) then - fonts = pdfdictionary { } - for k, v in next, usedfonts do - fonts[f_font(v)] = pdfreference(pdfgetfontobjnumber(k)) -- we can overload for testing - end - end - - -- messy: use real indexes for both ... so we need to change some in the - -- full luatex part - - if next(usedxforms) or next(usedximages) or next(usedxgroups) then - xforms = pdfdictionary { } - for k in sortedhash(usedxforms) do - -- xforms[f_form(k)] = pdfreference(k) - xforms[f_form(getxformname(k))] = pdfreference(k) - end - for k, v in sortedhash(usedximages) do - xforms[f_image(k)] = pdfreference(v) - end - for k, v in sortedhash(usedxgroups) do - xforms[f_group(k)] = pdfreference(v) - end - end - - reset_buffer() - - -- finish_pdfpage_callback(shippingmode == "page") - - if shippingmode == "page" then - - local pageproperties = lpdf.getpageproperties() - - local pageresources = pageproperties.pageresources - local pageattributes = pageproperties.pageattributes - local pagesattributes = pageproperties.pagesattributes - - pageresources.Font = fonts - pageresources.XObject = xforms - pageresources.ProcSet = lpdf.procset() - - local xorigin, yorigin, relocated = backends.codeinjections.getpageorigin() -- for now here - - local bbox = pdfarray { - (boundingbox[1] + xorigin) * bpfactor, - (boundingbox[2] + yorigin) * bpfactor, - (boundingbox[3] + xorigin) * bpfactor, - (boundingbox[4] + yorigin) * bpfactor, - } - - if relocated then - content = formatters["1 0 0 1 %.6N %.6N cm\n%s"](bbox[1],bbox[2],content) - end - - local contentsobj = pdfflushstreamobject(content,false,false) - - pageattributes.Type = pdf_page - pageattributes.Contents = pdfreference(contentsobj) - pageattributes.Resources = pageresources - -- pageattributes.Resources = pdfreference(pdfflushobject(pageresources)) - pageattributes.MediaBox = bbox - pageattributes.Parent = nil -- precalculate - pageattributes.Group = nil -- todo - - -- resources can be indirect - - registerpage(pageattributes) - - lpdf.finalizepage(true) - - if relocated then - if pageattributes.TrimBox then pageattributes.TrimBox = box end - if pageattributes.CropBox then pageattributes.CropBox = box end - if pageattributes.BleedBox then pageattributes.BleedBox = box end - end - - else - - local xformtype = specification.type or 0 - local margin = specification.margin or 0 - local attributes = specification.attributes or "" - local resources = specification.resources or "" - - local wrapper = nil - - if xformtype == 0 then - wrapper = pdfdictionary { - Type = pdf_xobject, - Subtype = pdf_form, - FormType = 1, - BBox = nil, - Matrix = nil, - Resources = nil, - } - else - wrapper = pdfdictionary { - BBox = nil, - Matrix = nil, - Resources = nil, - } - end - if xformtype == 0 or xformtype == 1 or xformtype == 3 then - wrapper.BBox = pdfarray { - -margin * bpfactor, - -margin * bpfactor, - (boundingbox[3] + margin) * bpfactor, - (boundingbox[4] + margin) * bpfactor, - } - end - if xformtype == 0 or xformtype == 2 or xformtype == 3 then - wrapper.Matrix = pdfarray { 1, 0, 0, 1, 0, 0 } - end - - -- todo: additional = resources - - local boxresources = lpdf.collectedresources { serialize = false } - boxresources.Font = fonts - boxresources.XObject = xforms - - -- todo: maybe share them - -- wrapper.Resources = pdfreference(pdfflushobject(boxresources)) - - if resources ~= "" then - boxresources = boxresources + resources - end - if attributes ~= "" then - wrapper = wrapper + attributes - end - - wrapper.Resources = next(boxresources) and boxresources or nil - wrapper.ProcSet = lpdf.procset() - - -- pdfflushstreamobject(content,wrapper,false,objectnumber) - pdfflushstreamobject(content,wrapper,false,specification.objnum) - - end - - for objnum in sortedhash(usedxforms) do - local f = flushedxforms[objnum] - if f[1] == false then - f[1] = true - local objnum = f[2] -- specification.objnum - local specification = boxresources[objnum] - local list = specification.list - localconverter(list,"xform",f[2],specification) - end - end - - pdf_h, pdf_v = 0, 0 - - if level == 1 then - flushdeferred() - end - level = level - 1 - - end - -end - -updaters.register("backend.update.pdf",function() - job.positions.registerhandlers { - getpos = drivers.getpos, - getrpos = drivers.getrpos, - gethpos = drivers.gethpos, - getvpos = drivers.getvpos, - } -end) - -updaters.register("backend.update",function() - local saveboxresource = tex.boxresources.save - -- - -- also in lpdf-res .. brrr .. needs fixing - -- - backends.codeinjections.registerboxresource = function(n,offset) - local r = saveboxresource(n,nil,nil,false,0,offset or 0) - return r - end -end) - --- now comes the pdf file handling - -local objects = { } -local streams = { } -- maybe just parallel to objects (no holes) -local nofobjects = 0 -local offset = 0 -local f = false -local flush = false -local threshold = 40 -- also #("/Filter /FlateDecode") (compression threshold) -local objectstream = true -local compress = true -local cache = false -local info = "" -local catalog = "" -local lastdeferred = false -local majorversion = 1 -local minorversion = 7 -local trailerid = true - -directives.register("backend.pdf.threshold",function(v) - if v then - threshold = tonumber(v) or 40 - else - threshold = -1000 - end -end) - -local f_object = formatters["%i 0 obj\010%s\010endobj\010"] -local f_stream_n_u = formatters["%i 0 obj\010<< /Length %i >>\010stream\010%s\010endstream\010endobj\010"] -local f_stream_n_c = formatters["%i 0 obj\010<< /Filter /FlateDecode /Length %i >>\010stream\010%s\010endstream\010endobj\010"] -local f_stream_d_u = formatters["%i 0 obj\010<< %s /Length %i >>\010stream\010%s\010endstream\010endobj\010"] -local f_stream_d_c = formatters["%i 0 obj\010<< %s /Filter /FlateDecode /Length %i >>\010stream\010%s\010endstream\010endobj\010"] -local f_stream_d_r = formatters["%i 0 obj\010<< %s >>\010stream\010%s\010endstream\010endobj\010"] - ------ f_object_b = formatters["%i 0 obj\010"] -local f_stream_b_n_u = formatters["%i 0 obj\010<< /Length %i >>\010stream\010"] -local f_stream_b_n_c = formatters["%i 0 obj\010<< /Filter /FlateDecode /Length %i >>\010stream\010"] -local f_stream_b_d_u = formatters["%i 0 obj\010<< %s /Length %i >>\010stream\010"] -local f_stream_b_d_c = formatters["%i 0 obj\010<< %s /Filter /FlateDecode /Length %i >>\010stream\010"] -local f_stream_b_d_r = formatters["%i 0 obj\010<< %s >>\010stream\010"] - ------ s_object_e = "\010endobj\010" -local s_stream_e = "\010endstream\010endobj\010" - -do - - local function setinfo() end -- we get it - local function setcatalog() end -- we get it - - local function settrailerid(v) - trailerid = v or false - end - - local function setmajorversion(v) majorversion = tonumber(v) or majorversion end - local function setminorversion(v) minorversion = tonumber(v) or minorversion end - - local function getmajorversion(v) return majorversion end - local function getminorversion(v) return minorversion end - - local function setcompresslevel (v) compress = v and v ~= 0 and true or false end - local function setobjcompresslevel(v) objectstream = v and v ~= 0 and true or false end - - local function getcompresslevel (v) return compress and 3 or 0 end - local function getobjcompresslevel(v) return objectstream and 1 or 0 end - - local function setpageresources () end -- needs to be sorted out - local function setpageattributes () end - local function setpagesattributes() end - - updaters.register("backend.update.pdf",function() - pdf.setinfo = setinfo - pdf.setcatalog = setcatalog - pdf.settrailerid = settrailerid - pdf.setmajorversion = setmajorversion - pdf.setminorversion = setminorversion - pdf.getmajorversion = getmajorversion - pdf.getminorversion = getminorversion - pdf.setcompresslevel = setcompresslevel - pdf.setobjcompresslevel = setobjcompresslevel - pdf.getcompresslevel = getcompresslevel - pdf.getobjcompresslevel = getobjcompresslevel - pdf.setpageresources = setpageresources - pdf.setpageattributes = setpageattributes - pdf.setpagesattributes = setpagesattributes - end) - -end - -local addtocache, flushcache, cache do - - local data, d = { }, 0 - local list, l = { }, 0 - local coffset = 0 - local indices = { } - - local maxsize = 32 * 1024 -- uncompressed - local maxcount = 0xFF - - addtocache = function(n,str) - local size = #str - if size == 0 then - -- todo: message - return - end - if coffset + size > maxsize or d == maxcount then - flushcache() - end - if d == 0 then - nofobjects = nofobjects + 1 - objects[nofobjects] = false - streams[nofobjects] = indices - cache = nofobjects - end - objects[n] = - cache - indices[n] = d - d = d + 1 - -- can have a comment n 0 obj as in luatex - data[d] = str - l = l + 1 ; list[l] = n - l = l + 1 ; list[l] = coffset - coffset = coffset + size + 1 - end - - local p_ObjStm = pdfconstant("ObjStm") - - flushcache = function() -- references cannot be stored - if l > 0 then - list = concat(list," ") - data[0] = list - data = concat(data,"\010",0,d) - local strobj = pdfdictionary { - Type = p_ObjStm, - N = d, - First = #list + 1, - } - objects[cache] = offset - local b = nil - local e = s_stream_e - if compress then - local comp = zlibcompress(data,3) - if comp and #comp < #data then - data = comp - b = f_stream_b_d_c(cache,strobj(),#data) - else - b = f_stream_b_d_u(cache,strobj(),#data) - end - else - b = f_stream_b_d_u(cache,strobj(),#data) - end - flush(f,b) - flush(f,data) - flush(f,e) - offset = offset + #b + #data + #e - data, d = { }, 0 - list, l = { }, 0 - coffset = 0 - indices = { } - end - end - -end - -local function pdfreserveobj() - nofobjects = nofobjects + 1 - objects[nofobjects] = false - return nofobjects -end - -local pages = table.setmetatableindex(function(t,k) - local v = pdfreserveobj() - t[k] = v - return v -end) - -local function getpageref(n) - return pages[n] -end - -local function refobj() - -- not needed, as we have auto-delay -end - -local function flushnormalobj(data,n) - if not n then - nofobjects = nofobjects + 1 - n = nofobjects - end - data = f_object(n,data) - if level == 0 then - objects[n] = offset - offset = offset + #data - flush(f,data) - else - if not lastdeferred then - lastdeferred = n - elseif n < lastdeferred then - lastdeferred = n - end - objects[n] = data - end - return n -end - -local function flushstreamobj(data,n,dict,comp,nolength) - if not data then - report("no data for %S",dict) - return - end - if not n then - nofobjects = nofobjects + 1 - n = nofobjects - end - local size = #data - if level == 0 then - local b = nil - local e = s_stream_e - if nolength then - b = f_stream_b_d_r(n,dict) - elseif comp ~= false and compress and size > threshold then - local compdata = zlibcompress(data,3) - if compdata then - local compsize = #compdata - if compsize > size - threshold then - b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size) - else - data = compdata - b = dict and f_stream_b_d_c(n,dict,compsize) or f_stream_b_n_c(n,compsize) - end - else - b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size) - end - else - b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size) - end - flush(f,b) - flush(f,data) - flush(f,e) - objects[n] = offset - offset = offset + #b + #data + #e - else - if nolength then - data = f_stream_d_r(n,dict,data) - elseif comp ~= false and compress and size > threshold then - local compdata = zlibcompress(data,3) - if compdata then - local compsize = #compdata - if compsize > size - threshold then - data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data) - else - data = dict and f_stream_d_c(n,dict,compsize,compdata) or f_stream_n_c(n,compsize,compdata) - end - else - data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data) - end - else - data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data) - end - if not lastdeferred then - lastdeferred = n - elseif n < lastdeferred then - lastdeferred = n - end - objects[n] = data - end - return n -end - -flushdeferred = function() -- was forward defined - if lastdeferred then - for n=lastdeferred,nofobjects do - local o = objects[n] - if type(o) == "string" then - objects[n] = offset - offset = offset + #o - flush(f,o) - end - end - lastdeferred = false - end -end - --- n = pdf.obj([n,] objtext) --- n = pdf.obj([n,] "file", filename) --- n = pdf.obj([n,] "stream", streamtext [, attrtext]) --- n = pdf.obj([n,] "streamfile", filename [, attrtext]) --- --- n = pdf.obj { --- type = , -- raw|stream --- immediate = , --- objnum = , --- attr = , --- compresslevel = , --- objcompression = , --- file = , --- string = , --- nolength = , --- } - -local function obj(a,b,c,d) - local kind --, immediate - local objnum, data, attr, filename - local compresslevel, objcompression, nolength - local argtype = type(a) - if argtype == "table" then - kind = a.type -- raw | stream - -- immediate = a.immediate - objnum = a.objnum - attr = a.attr - compresslevel = a.compresslevel - objcompression = a.objcompression - filename = a.file - data = a.string or a.stream or "" - nolength = a.nolength - if kind == "stream" then - if filename then - data = loaddata(filename) or "" - end - elseif kind == "raw"then - if filename then - data = loaddata(filename) or "" - end - elseif kind == "file"then - kind = "raw" - data = filename and loaddata(filename) or "" - elseif kind == "streamfile" then - kind = "stream" - data = filename and loaddata(filename) or "" - end - else - if argtype == "number" then - objnum = a - a, b, c = b, c, d - else - nofobjects = nofobjects + 1 - objnum = nofobjects - end - if b then - if a == "stream" then - kind = "stream" - data = b - elseif a == "file" then - -- kind = "raw" - data = loaddata(b) - elseif a == "streamfile" then - kind = "stream" - data = loaddata(b) - else - data = "" -- invalid object - end - attr = c - else - -- kind = "raw" - data = a - end - end - if not objnum then - nofobjects = nofobjects + 1 - objnum = nofobjects - end - -- todo: immediate - if kind == "stream" then - flushstreamobj(data,objnum,attr,compresslevel and compresslevel > 0 or nil,nolength) - elseif objectstream and objcompression ~= false then - addtocache(objnum,data) - else - flushnormalobj(data,objnum) - end - return objnum -end - -updaters.register("backend.update.pdf",function() - pdf.reserveobj = pdfreserveobj - pdf.getpageref = getpageref - pdf.refobj = refobj - pdf.flushstreamobj = flushstreamobj - pdf.flushnormalobj = flushnormalobj - pdf.obj = obj - pdf.immediateobj = obj -end) - --- In lua 5.4 the methods are now moved one metalevel deeper so we need to get them --- from mt.__index instead. (I did get that at first.) It makes for a slightly (imo) --- nicer interface but no real gain in speed as we don't flush that often. - -local openfile, closefile do - - -- I used to do but then figured out that when I open and save a file in a mode - -- that removes trailing spaces, the xref becomes invalid. The problem was then that a - -- reconstruction of the file by a viewer gives weird effects probably because percent symbols - -- gets interpreted then. Thanks to Ross Moore for noticing this side effect! - - local f_used = formatters["%010i 00000 n\013\010"] - local f_link = formatters["%010i 00000 f\013\010"] - local f_first = formatters["%010i 65535 f\013\010"] - - local f_pdf = formatters["%%PDF-%i.%i\010"] - local f_xref = formatters["xref\0100 %i\010"] - local f_trailer_id = formatters["trailer\010<< %s /ID [ <%s> <%s> ] >>\010startxref\010%i\010%%%%EOF"] - local f_trailer_no = formatters["trailer\010<< %s >>\010startxref\010%i\010%%%%EOF"] - local f_startxref = formatters["startxref\010%i\010%%%%EOF"] - - local inmemory = false - local close = false - - openfile = function(filename) - if inmemory then - local n = 0 - f = { } - flush = function(f,s) - n = n + 1 f[n] = s - end - close = function(f) - f = concat(f) - io.savedata(filename,f) - f = false - end - -- local n = 0 - -- f = { - -- write = function(self,s) - -- n = n + 1 f[n] = s - -- end, - -- close = function(self) - -- f = concat(f) - -- io.savedata(filename,f) - -- f = false - -- end, - -- } - else - f = io.open(filename,"wb") - if not f then - -- message - os.exit() - end - -- f:setvbuf("full",64*1024) - local m = getmetatable(f) - flush = m.write or m.__index.write - close = m.close or m.__index.close - end - local v = f_pdf(majorversion,minorversion) - -- local b = "%\xCC\xD5\xC1\xD4\xC5\xD8\xD0\xC4\xC6\010" -- LUATEXPDF (+128) - local b = "%\xC3\xCF\xCE\xD4\xC5\xD8\xD4\xD0\xC4\xC6\010" -- CONTEXTPDF (+128) - flush(f,v) - flush(f,b) - offset = #v + #b - end - - closefile = function(abort) - if abort then - f:close() - if not environment.arguments.nodummy then - f = io.open(abort,"wb") - if f then - local name = resolvers.findfile("context-lmtx-error.pdf") - if name then - local data = io.loaddata(name) - if data then - f:write(data) - f:close() - return - end - end - f:close() - end - end - removefile(abort) - else - local xrefoffset = offset - local lastfree = 0 - local noffree = 0 - local catalog = lpdf.getcatalog() - local info = lpdf.getinfo() - if trailerid == true then - trailerid = md5HEX(osuuid()) - elseif trailerid and #trailerid > 32 then - trailerid = md5HEX(trailerid) - else - trailerid = false - end - if objectstream then - flushdeferred() - flushcache() - -- - xrefoffset = offset - -- - nofobjects = nofobjects + 1 - objects[nofobjects] = offset -- + 1 - -- - -- combine these three in one doesn't really give less code so - -- we go for the efficient ones - -- - local nofbytes = 4 - local c1, c2, c3, c4 - if offset <= 0xFFFF then - nofbytes = 2 - for i=1,nofobjects do - local o = objects[i] - if not o then - noffree = noffree + 1 - else - local strm = o < 0 - if strm then - o = -o - end - c1 = extract(o,8,8) - c2 = extract(o,0,8) - if strm then - objects[i] = char(2,c1,c2,streams[o][i]) - else - objects[i] = char(1,c1,c2,0) - end - end - end - if noffree > 0 then - for i=nofobjects,1,-1 do - local o = objects[i] - if not o then - local f1 = extract(lastfree,8,8) - local f2 = extract(lastfree,0,8) - objects[i] = char(0,f1,f2,0) - lastfree = i - end - end - end - elseif offset <= 0xFFFFFF then - nofbytes = 3 - for i=1,nofobjects do - local o = objects[i] - if not o then - noffree = noffree + 1 - else - local strm = o < 0 - if strm then - o = -o - end - c1 = extract(o,16,8) - c2 = extract(o, 8,8) - c3 = extract(o, 0,8) - if strm then - objects[i] = char(2,c1,c2,c3,streams[o][i]) - else - objects[i] = char(1,c1,c2,c3,0) - end - end - end - if noffree > 0 then - for i=nofobjects,1,-1 do - local o = objects[i] - if not o then - local f1 = extract(lastfree,16,8) - local f2 = extract(lastfree, 8,8) - local f3 = extract(lastfree, 0,8) - objects[i] = char(0,f1,f2,f3,0) - lastfree = i - end - end - end - else - nofbytes = 4 - for i=1,nofobjects do - local o = objects[i] - if not o then - noffree = noffree + 1 - else - local strm = o < 0 - if strm then - o = -o - end - c1 = extract(o,24,8) - c2 = extract(o,16,8) - c3 = extract(o, 8,8) - c4 = extract(o, 0,8) - if strm then - objects[i] = char(2,c1,c2,c3,c4,streams[o][i]) - else - objects[i] = char(1,c1,c2,c3,c4,0) - end - end - end - if noffree > 0 then - for i=nofobjects,1,-1 do - local o = objects[i] - if not o then - local f1 = extract(lastfree,24,8) - local f2 = extract(lastfree,16,8) - local f3 = extract(lastfree, 8,8) - local f4 = extract(lastfree, 0,8) - objects[i] = char(0,f1,f2,f3,f4,0) - lastfree = i - end - end - end - end - objects[0] = rep("\0",1+nofbytes+1) - local data = concat(objects,"",0,nofobjects) - local xref = pdfdictionary { - Type = pdfconstant("XRef"), - Size = nofobjects + 1, - W = pdfarray { 1, nofbytes, 1 }, - Root = catalog, - Info = info, - ID = trailerid and pdfarray { pdfliteral(trailerid,true), pdfliteral(trailerid,true) } or nil, - } - if compress then - local comp = zlibcompress(data,3) - if comp then - data = comp - flush(f,f_stream_b_d_c(nofobjects,xref(),#data)) - else - flush(f,f_stream_b_d_u(nofobjects,xref(),#data)) - end - else - flush(f,f_stream_b_d_u(nofobjects,xref(),#data)) - end - flush(f,data) - flush(f,s_stream_e) - flush(f,f_startxref(xrefoffset)) - else - flushdeferred() - xrefoffset = offset - flush(f,f_xref(nofobjects+1)) - local trailer = pdfdictionary { - Size = nofobjects+1, - Root = catalog, - Info = info, - } - for i=1,nofobjects do - local o = objects[i] - if o then - objects[i] = f_used(o) - end - end - for i=nofobjects,1,-1 do - local o = objects[i] - if not o then - objects[i] = f_link(lastfree) - lastfree = i - end - end - objects[0] = f_first(lastfree) - flush(f,concat(objects,"",0,nofobjects)) - trailer.Size = nofobjects + 1 - if trailerid then - flush(f,f_trailer_id(trailer(),trailerid,trailerid,xrefoffset)) - else - flush(f,f_trailer_no(trailer(),xrefoffset)) - end - end - f:close() - end - io.flush() - closefile = function() end - end - -end - --- For the moment we overload it here, although back-fil.lua eventually will --- be merged with back-pdf as it's pdf specific, or maybe back-imp-pdf or so. - -updaters.register("backend.update.pdf",function() - - -- We overload img but at some point it will even go away, so we just - -- reimplement what we need in context. This will change completely i.e. - -- we will drop the low level interface! - - local codeinjections = backends.pdf.codeinjections - - local imagetypes = images.types -- pdf png jpg jp2 jbig2 stream memstream - local img_none = imagetypes.none - - local rulecodes = nodes.rulecodes - - local setprop = nodes.nuts.setprop - - local report_images = logs.reporter("backend","images") - - local lastindex = 0 - local indices = { } - - local bpfactor = number.dimenfactors.bp - local imagerule_code = rulecodes.image - - function codeinjections.newimage(specification) - return specification - end - - function codeinjections.copyimage(original) - return setmetatableindex(original) - end - - function codeinjections.scanimgage(specification) - return specification - end - - local function embedimage(specification) - if specification then - lastindex = lastindex + 1 - index = lastindex - specification.index = index - local xobject = pdfdictionary { } - if not specification.notype then - xobject.Type = pdf_xobject - xobject.Subtype = pdf_form - xobject.FormType = 1 - end - local bbox = specification.bbox - if bbox and not specification.nobbox then - xobject.BBox = pdfarray { - bbox[1] * bpfactor, - bbox[2] * bpfactor, - bbox[3] * bpfactor, - bbox[4] * bpfactor, - } - end - xobject = xobject + specification.attr - if bbox and not specification.width then - specification.width = bbox[3] - end - if bbox and not specification.height then - specification.height = bbox[4] - end - local dict = xobject() - -- - nofobjects = nofobjects + 1 - local objnum = nofobjects - local nolength = specification.nolength - local stream = specification.stream or specification.string - -- - -- We cannot set type in native img so we need this hack or - -- otherwise we need to patch too much. Better that i write - -- a wrapper then. Anyway, it has to be done better: a key that - -- tells either or not to scale by xsize/ysize when flushing. - -- - if not specification.type then - local kind = specification.kind - if kind then - -- take that one - elseif attr and find(attr,"BBox") then - kind = img_stream - else - -- hack: a bitmap - kind = img_none - end - specification.type = kind - specification.kind = kind - end - local compress = compresslevel and compresslevel > 0 or nil - flushstreamobj(stream,objnum,dict,compress,nolength) - specification.objnum = objnum - specification.rotation = specification.rotation or 0 - specification.orientation = specification.orientation or 0 - specification.transform = specification.transform or 0 - specification.stream = nil - specification.attr = nil - specification.type = specification.kind or specification.type or img_none - indices[index] = specification -- better create a real specification - return specification - end - end - - codeinjections.embedimage = embedimage - - function codeinjections.wrapimage(specification) - -- - local index = specification.index - if not index then - embedimage(specification) - end - -- - local width = specification.width or 0 - local height = specification.height or 0 - local depth = specification.depth or 0 - -- newimagerule - local n = nodes.pool.rule(width,height,depth) - n.subtype = imagerule_code - setprop(tonut(n),"index",specification.index) - return n - end - - function pdf.includeimage(index) - local specification = indices[index] - if specification then - local bbox = specification.bbox - local xorigin = bbox[1] - local yorigin = bbox[2] - local xsize = bbox[3] - xorigin -- we need the original ones, not the 'rotated' ones - local ysize = bbox[4] - yorigin -- we need the original ones, not the 'rotated' ones - local transform = specification.transform or 0 - local objnum = specification.objnum or pdfreserveobj() - local groupref = nil - local kind = specification.kind or specification.type or img_none -- determines scaling type - return - kind, - xorigin, yorigin, - xsize, ysize, - transform, - objnum, - groupref - end - end - -end) - -updaters.register("backend.update.lpdf",function() - - -- todo: an md5 or sha2 hash can save space - -- todo: make a type 3 font instead - -- todo: move to lpdf namespace - - local pdfimage = lpdf.epdf.image - local newpdf = pdfimage.new - local openpdf = pdfimage.open - local closepdf = pdfimage.close - local copypage = pdfimage.copy - - local embedimage = images.embed - - local nofstreams = 0 - local topdf = { } - local toidx = { } - - local function storedata_s(pdf) - local idx = toidx[pdf] - if not idx then - nofstreams = nofstreams + 1 - idx = nofstreams - toidx[pdf] = nofstreams - topdf[idx] = pdf - end - return idx - end - - local function vfimage_s(id,wd,ht,dp,pos_h,pos_v) - local index = topdf[id] - if type(index) == "string" then - local pdfdoc = newpdf(index,#index) - local image = copypage(pdfdoc) - local bbox = image.bbox - image.width = bbox[3] - bbox[1] - image.height = bbox[4] - bbox[2] - embedimage(image) - index = image.index - topdf[id] = index - end - -- pdf.print or pdf.literal - flushimage(index,wd,ht,dp,pos_h,pos_v) - end - - local function storedata_n(name,page) - local idx = toidx[pdf] - if not idx then - nofstreams = nofstreams + 1 - idx = nofstreams - toidx[pdf] = nofstreams - topdf[idx] = pdf - end - return idx - end - - -- We need to have a way to close such a pdf ... esp for fonts. - - local pdfdocs = { } - - local function vfimage_n(name,page,wd,ht,dp,pos_h,pos_v) - local d = pdfdocs[name] - if not d then - d = { doc = openpdf(name), pages = { } } - pdfdocs[name] = d - end - local index = d.pages[page] - if not index then - local image = copypage(d.doc,page) - local bbox = image.bbox - image.width = bbox[3] - bbox[1] - image.height = bbox[4] - bbox[2] - embedimage(image) - index = image.index - d.pages[page] = index - end - flushimage(index,wd,ht,dp,pos_h,pos_v) - end - - local function pdfvfimage(wd,ht,dp,data,name) - if type(data) == "number" then - return { "lua", function(font,char,pos_h,pos_v) - vfimage_n(name,data,wd,ht,dp,pos_h,pos_v) - end } - else - return { "lua", function(font,char,pos_h,pos_v) - local id = storedata_s(data) - vfimage_s(id,wd,ht,dp,pos_h,pos_v) - end } - end - end - - lpdf.vfimage = pdfvfimage - -end) - --- The driver. - -do - - local isfile = lfs.isfile - local removefile = os.remove - local renamefile = os.rename - -- local copyfile = file.copy - -- local addsuffix = file.addsuffix - local texgetbox = tex.getbox - - local pdfname = nil - local converter = nil - local useddriver = nil -- a bit of a hack - - local function outputfilename(driver) - return pdfname - end - - -- todo: prevent twice - - local function prepare(driver) - if not environment.initex then - -- install new functions in pdf namespace - updaters.apply("backend.update.pdf") - -- install new functions in lpdf namespace - updaters.apply("backend.update.lpdf") - -- adapt existing shortcuts to lpdf namespace - updaters.apply("backend.update.tex") - -- adapt existing shortcuts to tex namespace - updaters.apply("backend.update") - -- - -- if rawget(pdf,"setforcefile") then - -- pdf.setforcefile(false) -- default anyway - -- end - -- - -- pdfname = file.addsuffix(tex.jobname,"pdf") - pdfname = tex.jobname .. ".pdf" - openfile(pdfname) - -- - luatex.registerstopactions(1,function() - if pdfname then - lpdf.finalizedocument() - closefile() - end - end) - -- - luatex.registerpageactions(1,function() - if pdfname then - lpdf.finalizepage(true) - end - end) - -- -- - lpdf.registerdocumentfinalizer(wrapup,nil,"wrapping up") - -- - end - -- - environment.lmtxmode = CONTEXTLMTXMODE - -- - converter = drivers.converters.lmtx - useddriver = driver - end - - local function wrapup(driver) - if pdfname then - closefile() - pdfname = nil - end - end - - local function cleanup(driver) - if pdfname then - closefile(pdfname) - pdfname = nil - end - end - - local function convert(driver,boxnumber) - converter(driver,texgetbox(boxnumber),"page") - end - - localconverter = function(...) - converter(useddriver,...) - end - - drivers.install { - name = "pdf", - flushers = { - character = flushcharacter, - fontchar = flushfontchar, - rule = flushrule, - simplerule = flushsimplerule, - pushorientation = pushorientation, - poporientation = poporientation, - -- - literal = flushliteral, - setmatrix = flushsetmatrix, - save = flushsave, - restore = flushrestore, - image = flushimage, - group = flushgroup, - -- - updatefontstate = updatefontstate, - }, - actions = { - prepare = prepare, - wrapup = wrapup, - cleanup = cleanup, - -- - initialize = initialize, - convert = convert, - finalize = finalize, - -- - outputfilename = outputfilename, - }, - } - -end diff --git a/tex/context/base/mkiv/lpdf-vfc.lmt b/tex/context/base/mkiv/lpdf-vfc.lmt new file mode 100644 index 000000000..65b863203 --- /dev/null +++ b/tex/context/base/mkiv/lpdf-vfc.lmt @@ -0,0 +1,40 @@ +if not modules then modules = { } end modules ['lpdf-vfc'] = { + 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 setmetatableindex = table.setmetatableindex + +local defaultline = 16384 +local vfspecials = backends.pdf.tables.vfspecials + +vfspecials.backgrounds = setmetatableindex(function(t,h) + local v = setmetatableindex(function(t,d) + local v = setmetatableindex(function(t,w) + local v = { "frame", w, h, d, defaultline, true, true } + t[w] = v + return v + end) + t[d] = v + return v + end) + t[h] = v + return v +end) + +vfspecials.outlines = setmetatableindex(function(t,h) + local v = setmetatableindex(function(t,d) + local v = setmetatableindex(function(t,w) + local v = { "frame", w, h, d, defaultline, false, true } + t[w] = v + return v + end) + t[d] = v + return v + end) + t[h] = v + return v +end) diff --git a/tex/context/base/mkiv/lpdf-vfc.lua b/tex/context/base/mkiv/lpdf-vfc.lua new file mode 100644 index 000000000..5c1937ab9 --- /dev/null +++ b/tex/context/base/mkiv/lpdf-vfc.lua @@ -0,0 +1,50 @@ +if not modules then modules = { } end modules ['lpdf-vfc'] = { + 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 setmetatableindex = table.setmetatableindex +local formatters = string.formatters + +local bp = number.dimenfactors.bp +local r = 16384 * bp +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"] + +local vfspecials = backends.pdf.tables.vfspecials + +vfspecials.backgrounds = setmetatableindex(function(t,h) + local h = h * bp + local v = setmetatableindex(function(t,d) + local d = d * bp + local v = setmetatableindex(function(t,w) + local v = { "pdf", "origin", f_1(r,-d,w*bp,h+d) } + t[w] = v + return v + end) + t[d] = v + return v + end) + t[h] = v + return v +end) + +vfspecials.outlines = setmetatableindex(function(t,h) + local h = h * bp + local v = setmetatableindex(function(t,d) + local d = d * bp + local v = setmetatableindex(function(t,w) + -- the frame goes through the boundingbox + local v = { "pdf", "origin", f_2(r,r/2,-d+r/2,w*bp-r,h+d-r) } + t[w] = v + return v + end) + t[d] = v + return v + end) + t[h] = v + return v +end) diff --git a/tex/context/base/mkiv/mlib-ctx.mkiv b/tex/context/base/mkiv/mlib-ctx.mkiv index 61b02ad88..7fb567746 100644 --- a/tex/context/base/mkiv/mlib-ctx.mkiv +++ b/tex/context/base/mkiv/mlib-ctx.mkiv @@ -13,6 +13,7 @@ \writestatus{loading}{MetaPost Library Graphics / Initializations} +\registerctxluafile{mlib-fio}{} \registerctxluafile{mlib-run}{} \registerctxluafile{mlib-ctx}{} \registerctxluafile{mlib-lua}{autosuffix} diff --git a/tex/context/base/mkiv/mlib-ctx.mkxl b/tex/context/base/mkiv/mlib-ctx.mkxl index 8069f5932..88f26c9ac 100644 --- a/tex/context/base/mkiv/mlib-ctx.mkxl +++ b/tex/context/base/mkiv/mlib-ctx.mkxl @@ -13,6 +13,7 @@ \writestatus{loading}{MetaPost Library Graphics / Initializations} +\registerctxluafile{mlib-fio}{autosuffix} \registerctxluafile{mlib-run}{} \registerctxluafile{mlib-ctx}{} \registerctxluafile{mlib-lua}{autosuffix} diff --git a/tex/context/base/mkiv/mlib-fio.lmt b/tex/context/base/mkiv/mlib-fio.lmt new file mode 100644 index 000000000..4290537dd --- /dev/null +++ b/tex/context/base/mkiv/mlib-fio.lmt @@ -0,0 +1,191 @@ +if not modules then modules = { } end modules ['mlib-run'] = { + version = 1.001, + comment = "companion to mlib-ctx.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", +} + +local type = type +local find = string.find +local concat = table.concat + +local trace_terminal = false trackers.register("metapost.terminal", function(v) trace_terminal = v end) + +local report_metapost = logs.reporter("metapost") +local report_terminal = logs.reporter("metapost","terminal") +local report_logger = logs.reporter("metapost","log") +local report_error = logs.reporter("metapost","error") + +mplib.realtimelogging = false + +local l, nl, dl = { }, 0, false +local t, nt, dt = { }, 0, false +local e, ne, de = { }, 0, false + +local function logger(target,str) + if target == 1 then + -- log + elseif target == 2 or target == 3 then + -- term + if str == "\n" then + mplib.realtimelogging = true + if nl > 0 then + report_logger(concat(l,"",1,nl)) + nl, dl = 0, false + elseif not dl then + report_logger("") + dl = true + end + else + nl = nl + 1 + l[nl] = str + end + elseif target == 4 then + report_error(str) + end +end + +local finders = { } +mplib.finders = finders -- also used in meta-lua.lua + +local new_instance = mplib.new + +local function validftype(ftype) + if ftype == "mp" then + return "mp" + else + return nil + end +end + +finders.file = function(specification,name,mode,ftype) + return resolvers.findfile(name,validftype(ftype)) +end + +local findtexfile = resolvers.findtexfile +local opentexfile = resolvers.opentexfile +local splitlines = string.splitlines + +local function writetoterminal(terminaldata,maxterm,d) + local t = type(d) + local n = 0 + if t == "string" then + d = splitlines(d) + n = #d + for i=1,#d do + maxterm = maxterm + 1 + terminaldata[maxterm] = d[i] + end + elseif t == "table" then + for i=1,#d do + local l = d[i] + if find(l,"[\n\r]") then + local s = splitlines(l) + local m = #s + for i=1,m do + maxterm = maxterm + 1 + terminaldata[maxterm] = s[i] + end + n = n + m + else + maxterm = maxterm + 1 + terminaldata[maxterm] = d[i] + n = 1 + end + end + end + if trace_terminal then + report_metapost("writing %i lines, in cache %s",n,maxterm) + end + return maxterm +end + +local function readfromterminal(terminaldata,maxterm,nowterm) + if nowterm >= maxterm then + terminaldata[nowterm] = false + maxterm = 0 + nowterm = 0 + if trace_terminal then + report_metapost("resetting, maxcache %i",#terminaldata) + end + return maxterm, nowterm, nil + else + if nowterm > 0 then + terminaldata[nowterm] = false + end + nowterm = nowterm + 1 + local s = terminaldata[nowterm] + if trace_terminal then + report_metapost("reading line %i: %s",nowterm,s) + end + return maxterm, nowterm, s + end +end + +local function fileopener() + + -- these can go into the table itself + + local terminaldata = { } + local maxterm = 0 + local nowterm = 0 + + local terminal = { + name = "terminal", + close = function() + -- terminal = { } + -- maxterm = 0 + -- nowterm = 0 + end, + reader = function() + local line + maxterm, nowterm, line = readfromterminal(terminaldata,maxterm,nowterm) + return line + end, + writer = function(d) + maxterm = writetoterminal(terminaldata,maxterm,d) + end, + } + + return function(name,mode,kind) + if name == "terminal" then + -- report_metapost("opening terminal") + return terminal + elseif mode == "w" then + local f = io.open(name,"wb") + if f then + -- report_metapost("opening file %a for writing",full) + return { + name = full, + writer = function(s) return f:write(s) end, -- io.write(f,s) + close = function() f:close() end, + } + end + else + local full = findtexfile(name,validftype(ftype)) + if full then + -- report_metapost("opening file %a for reading",full) + return opentexfile(full) + end + end + end + +end + +local function finder(name,mode,kind) + return findtexfile(name,kind) +end + +function mplib.new(specification) + local openfile = fileopener() + specification.find_file = finder + specification.run_logger = logger + specification.open_file = openfile + specification.interaction = "silent" + specification.halt_on_error = true + local instance = new_instance(specification) + return instance, openfile("terminal") +end + +mplib.finder = finder diff --git a/tex/context/base/mkiv/mlib-fio.lua b/tex/context/base/mkiv/mlib-fio.lua new file mode 100644 index 000000000..51c88eb22 --- /dev/null +++ b/tex/context/base/mkiv/mlib-fio.lua @@ -0,0 +1,85 @@ +if not modules then modules = { } end modules ['mlib-run'] = { + version = 1.001, + comment = "companion to mlib-ctx.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", +} + +local concat = table.concat +local mplib = mplib + +local report_logger = logs.reporter("metapost log") +local report_error = logs.reporter("metapost error") + +local l, nl, dl = { }, 0, false +local t, nt, dt = { }, 0, false +local e, ne, de = { }, 0, false + +mplib.realtimelogging = false + +local function logger(target,str) + if target == 1 then + -- log + elseif target == 2 or target == 3 then + -- term + if str == "\n" then + mplib.realtimelogging = true + if nl > 0 then + report_logger(concat(l,"",1,nl)) + nl, dl = 0, false + elseif not dl then + report_logger("") + dl = true + end + else + nl = nl + 1 + l[nl] = str + end + elseif target == 4 then + report_error(str) + end +end + +local finders = { } +mplib.finders = finders -- also used in meta-lua.lua + +local new_instance = mplib.new + +local function validftype(ftype) + if ftype == "mp" then + return "mp" + else + return nil + end +end + +finders.file = function(specification,name,mode,ftype) + return resolvers.findfile(name,validftype(ftype)) +end + +local function i_finder(name,mode,ftype) -- fake message for mpost.map and metafun.mpvi + local specification = url.hashed(name) + local finder = finders[specification.scheme] or finders.file + local found = finder(specification,name,mode,validftype(ftype)) + return found +end + +local function o_finder(name,mode,ftype) + return name +end + +o_finder = sandbox.register(o_finder,sandbox.filehandlerone,"mplib output finder") + +local function finder(name,mode,ftype) + return (mode == "w" and o_finder or i_finder)(name,mode,validftype(ftype)) +end + +function mplib.new(specification) + specification.find_file = finder + specification.run_logger = logger + return new_instance(specification) +end + +mplib.finder = finder + diff --git a/tex/context/base/mkiv/mlib-lua.lmt b/tex/context/base/mkiv/mlib-lua.lmt index ed65b9401..30fc2ff63 100644 --- a/tex/context/base/mkiv/mlib-lua.lmt +++ b/tex/context/base/mkiv/mlib-lua.lmt @@ -45,6 +45,12 @@ scan.transform = function(t) return scan_transform (currentmpx,t) end scan.path = function(t) return scan_path (currentmpx,t) end scan.pen = function(t) return scan_pen (currentmpx,t) end +local solve_path = mplib.solve_path + +mp.solve = function(...) + return solve_path(currentmpx,...) +end + local inject_path = mplib.inject_path local inject_numeric = mplib.inject_numeric local inject_pair = mplib.inject_pair @@ -56,7 +62,7 @@ local inject_cmykcolor = mplib.inject_cmykcolor local inject_transform = mplib.inject_transform local inject_whatever = mplib.inject_whatever -inject.path = function(t,cycle,curled) return inject_path (currentmpx,t,cycle,curled) end +------.path = function(t,cycle,curled) return inject_path (currentmpx,t,cycle,curled) end inject.numeric = function(n) return inject_numeric (currentmpx,n) end inject.pair = function(x,y) return inject_pair (currentmpx,x,y) end inject.boolean = function(b) return inject_boolean (currentmpx,b) end @@ -67,6 +73,47 @@ inject.cmykcolor = function(c,m,y,k) return inject_cmykcolor(currentmpx, inject.transform = function(x,y,xx,xy,yx,yy) return inject_transform(currentmpx,x,y,xx,xy,yx,yy) end inject.whatever = function(...) return inject_whatever (currentmpx,...) end +local function same(p,n) + local f = p[1] + local l = p[n] + local nf = #f + local nl = #l + if nf == nl then + for i=1,nf do + if f[i] ~= l[i] then + return false + end + end + return true + end + return false +end + +-- local p = mp.scan.path() +-- mp.inject.path(p,true,true) + +function inject.path(p,close,connector) + local curled = false + local n = #p + if p.close then + close = true + end + if n > 1 then + -- [ ../true | --/false | nil/auto ] + if connector == nil or connector == "auto" then + connector = #p[1] > 2 + end + if connector == false or connector == "--" then + curled = true + elseif connector == true or connector == ".." then + if close and not same(p,n) then + p[n+1] = p[1] + end + end + end + return inject_path(currentmpx,p,curled,close) +end + -- bonus: scan .number = scan .numeric diff --git a/tex/context/base/mkiv/mlib-run.lua b/tex/context/base/mkiv/mlib-run.lua index 6962340c5..5aa9c78d0 100644 --- a/tex/context/base/mkiv/mlib-run.lua +++ b/tex/context/base/mkiv/mlib-run.lua @@ -34,14 +34,11 @@ local find, striplines = string.find, utilities.strings.striplines local concat, insert, remove = table.concat, table.insert, table.remove local emptystring = string.is_empty -local P = lpeg.P local trace_graphics = false trackers.register("metapost.graphics", function(v) trace_graphics = v end) local trace_tracingall = false trackers.register("metapost.tracingall", function(v) trace_tracingall = v end) -local trace_terminal = false trackers.register("metapost.terminal", function(v) trace_terminal = v end) local report_metapost = logs.reporter("metapost") -local report_terminal = logs.reporter("metapost","terminal") local texerrormessage = logs.texerrormessage local starttiming = statistics.starttiming @@ -60,9 +57,9 @@ metapost.exectime = metapost.exectime or { } -- hack metapost.nofruns = 0 local mpxformats = { } -local mpxterminals = { } local nofformats = 0 local mpxpreambles = { } +local mpxterminals = { } local mpxextradata = { } -- The flatten hack is needed because the library currently barks on \n\n and the @@ -112,234 +109,6 @@ function metapost.resetlastlog() metapost.lastlog = "" end ------ mpbasepath = lpeg.instringchecker(lpeg.append { "/metapost/context/", "/metapost/base/" }) -local mpbasepath = lpeg.instringchecker(P("/metapost/") * (P("context") + P("base")) * P("/")) - --- mplib has no real io interface so we have a different mechanism than --- tex (as soon as we have more control, we will use the normal code) --- --- for some reason mp sometimes calls this function twice which is inefficient --- but we cannot catch this - -local realtimelogging do - - -- begin of logger code - - local report_logger = logs.reporter("metapost log") - local report_error = logs.reporter("metapost error") - - local l, nl, dl = { }, 0, false - local t, nt, dt = { }, 0, false - local e, ne, de = { }, 0, false - - local function logger(target,str) - if target == 1 then - -- log - elseif target == 2 or target == 3 then - -- term - if str == "\n" then - realtimelogging = true - if nl > 0 then - report_logger(concat(l,"",1,nl)) - nl, dl = 0, false - elseif not dl then - report_logger("") - dl = true - end - else - nl = nl + 1 - l[nl] = str - end - elseif target == 4 then - report_error(str) - end - end - - -- end of logger code - - -- begin of logger code - - local finders = { } - mplib.finders = finders -- also used in meta-lua.lua - - local new_instance = mplib.new - - local function validftype(ftype) - if ftype == "mp" then - return "mp" - else - return nil - end - end - - finders.file = function(specification,name,mode,ftype) - return resolvers.findfile(name,validftype(ftype)) - end - - -- end of finder code - - if CONTEXTLMTXMODE > 0 then - - local findtexfile = resolvers.findtexfile - local opentexfile = resolvers.opentexfile - local splitlines = string.splitlines - - local function writetoterminal(terminaldata,maxterm,d) - local t = type(d) - local n = 0 - if t == "string" then - d = splitlines(d) - n = #d - for i=1,#d do - maxterm = maxterm + 1 - terminaldata[maxterm] = d[i] - end - elseif t == "table" then - for i=1,#d do - local l = d[i] - if find(l,"[\n\r]") then - local s = splitlines(l) - local m = #s - for i=1,m do - maxterm = maxterm + 1 - terminaldata[maxterm] = s[i] - end - n = n + m - else - maxterm = maxterm + 1 - terminaldata[maxterm] = d[i] - n = 1 - end - end - end - if trace_terminal then - report_metapost("writing %i lines, in cache %s",n,maxterm) - end - return maxterm - end - - local function readfromterminal(terminaldata,maxterm,nowterm) - if nowterm >= maxterm then - terminaldata[nowterm] = false - maxterm = 0 - nowterm = 0 - if trace_terminal then - report_metapost("resetting, maxcache %i",#terminaldata) - end - return maxterm, nowterm, nil - else - if nowterm > 0 then - terminaldata[nowterm] = false - end - nowterm = nowterm + 1 - local s = terminaldata[nowterm] - if trace_terminal then - report_metapost("reading line %i: %s",nowterm,s) - end - return maxterm, nowterm, s - end - end - - local function fileopener() - - -- these can go into the table itself - - local terminaldata = { } - local maxterm = 0 - local nowterm = 0 - - local terminal = { - name = "terminal", - close = function() - -- terminal = { } - -- maxterm = 0 - -- nowterm = 0 - end, - reader = function() - local line - maxterm, nowterm, line = readfromterminal(terminaldata,maxterm,nowterm) - return line - end, - writer = function(d) - maxterm = writetoterminal(terminaldata,maxterm,d) - end, - } - - return function(name,mode,kind) - if name == "terminal" then - -- report_metapost("opening terminal") - return terminal - elseif mode == "w" then - local f = io.open(name,"wb") - if f then - -- report_metapost("opening file %a for writing",full) - return { - name = full, - writer = function(s) return f:write(s) end, -- io.write(f,s) - close = function() f:close() end, - } - end - else - local full = findtexfile(name,validftype(ftype)) - if full then - -- report_metapost("opening file %a for reading",full) - return opentexfile(full) - end - end - end - - end - - local function finder(name,mode,kind) - return findtexfile(name,kind) - end - - function mplib.new(specification) - local openfile = fileopener() - specification.find_file = finder - specification.run_logger = logger - specification.open_file = openfile - specification.interaction = "silent" - specification.halt_on_error = true - local instance = new_instance(specification) - mpxterminals[instance] = openfile("terminal") - return instance - end - - mplib.finder = finder - - else - - local function i_finder(name,mode,ftype) -- fake message for mpost.map and metafun.mpvi - local specification = url.hashed(name) - local finder = finders[specification.scheme] or finders.file - local found = finder(specification,name,mode,validftype(ftype)) - return found - end - - local function o_finder(name,mode,ftype) - return name - end - - o_finder = sandbox.register(o_finder,sandbox.filehandlerone,"mplib output finder") - - local function finder(name,mode,ftype) - return (mode == "w" and o_finder or i_finder)(name,mode,validftype(ftype)) - end - - function mplib.new(specification) - specification.find_file = finder - specification.run_logger = logger - return new_instance(specification) - end - - mplib.finder = finder - - end - - -end - local new_instance = mplib.new local find_file = mplib.finder @@ -349,7 +118,7 @@ function metapost.reporterror(result) return true elseif result.status == 0 then return false - elseif realtimelogging then + elseif mplib.realtimelogging then return false -- we already reported else local t = result.term @@ -414,7 +183,7 @@ function metapost.load(name,method) end end method = method and methods[method] or "scaled" - local mpx = new_instance { + local mpx, terminal = new_instance { ini_version = true, math_mode = method, run_script = metapost.runscript, @@ -430,6 +199,7 @@ function metapost.load(name,method) if not mpx then result = { status = 99, error = "out of memory"} else + mpxterminals[mpx] = terminal -- pushing permits advanced features metapost.pushscriptrunner(mpx) result = executempx(mpx,f_preamble(file.addsuffix(name,"mp"),seed)) @@ -567,17 +337,17 @@ function metapost.reset(mpx) if mpxformats[mpx] then local instance = mpxformats[mpx] instance:finish() - mpxterminals[instance] = nil - mpxextradata[mpx] = nil - mpxformats [mpx] = nil + mpxterminals[mpx] = nil + mpxextradata[mpx] = nil + mpxformats [mpx] = nil end else for name, instance in next, mpxformats do if instance == mpx then mpx:finish() + mpxterminals[mpx] = nil mpxextradata[mpx] = nil mpxformats [mpx] = nil - mpxterminals[mpx] = nil break end end diff --git a/tex/context/base/mkiv/mlib-scn.lmt b/tex/context/base/mkiv/mlib-scn.lmt index 5655c507d..4c6c15a89 100644 --- a/tex/context/base/mkiv/mlib-scn.lmt +++ b/tex/context/base/mkiv/mlib-scn.lmt @@ -71,6 +71,7 @@ local injectpair = injectors.pair local injecttriplet = injectors.color local injectquadruple = injectors.cmykcolor local injecttransform = injectors.transform +local injectpath = injectors.path local report = logs.reporter("metapost") @@ -96,26 +97,6 @@ local tokenscanners = nil local scanset = nil local scanparameters = nil -local injectpath = mp.path - -do -- todo: this will become an overload - - local flush = mp.path - local inject = injectors.path -- work in progress - - injectpath = function(p,connector,close) - if #p > 1 then - if connector == true or connector == ".." then - return inject(p,false,close or p.close) - elseif connector == "--" then - return inject(p,true,close or p.close) - end - end - return flush(p,connector,close) - end - -end - scanset = function() -- can be optimized, we now read twice scantoken() if scantoken(true) == rightbrace_code then diff --git a/tex/context/base/mkiv/mult-def.lua b/tex/context/base/mkiv/mult-def.lua index 174a50cc6..dd10cca3e 100644 --- a/tex/context/base/mkiv/mult-def.lua +++ b/tex/context/base/mkiv/mult-def.lua @@ -75,7 +75,7 @@ return { ["cs"]="Kap", ["de"]="Kap", ["en"]="Cap", - ["fr"]="Cap", + ["fr"]="PetitesCap", ["it"]="Cap", ["nl"]="Kap", ["pe"]="Cap", @@ -85,7 +85,7 @@ return { ["cs"]="Kaps", ["de"]="Kaps", ["en"]="Caps", - ["fr"]="Caps", + ["fr"]="PetitesCaps", ["it"]="Caps", ["nl"]="Kaps", ["pe"]="Caps", @@ -145,7 +145,7 @@ return { ["cs"]="oref", ["de"]="ueber", ["en"]="about", - ["fr"]="concernant", + ["fr"]="apropos", ["it"]="intorno", ["nl"]="about", ["pe"]="درمورد", @@ -155,13 +155,18 @@ return { ["cs"]="prizpusobvzhled", ["de"]="passelayoutan", ["en"]="adaptlayout", - ["fr"]="adaptedisposition", + ["fr"]="adaptermiseenpage", ["it"]="adattalayout", ["nl"]="paslayoutaan", ["pe"]="تنظیم‌طرح‌بندی", ["ro"]="adapteazaaspect", }, ["adding"]={}, + ["alignment"]={ + ["en"]="alignment", + ["fr"]="alignement", + ["nl"]="uitlijnen", + }, ["arg"]={ ["cs"]="arg", ["de"]="arg", @@ -176,7 +181,7 @@ return { ["cs"]="pref", ["de"]="bei", ["en"]="at", - ["fr"]="a", + ["fr"]="en", ["it"]="al", ["nl"]="op", ["pe"]="در", @@ -186,7 +191,7 @@ return { ["cs"]="atleftmargin", ["de"]="atleftmargin", ["en"]="atleftmargin", - ["fr"]="atleftmargin", + ["fr"]="enmargegauche", ["it"]="atleftmargin", ["nl"]="oplinkermarge", ["pe"]="درحاشیه‌چپ", @@ -196,7 +201,7 @@ return { ["cs"]="nastrane", ["de"]="aufseite", ["en"]="atpage", - ["fr"]="alapage", + ["fr"]="enpage", ["it"]="apagina", ["nl"]="oppagina", ["pe"]="درصفحه", @@ -206,7 +211,7 @@ return { ["cs"]="atrightmargin", ["de"]="atrightmargin", ["en"]="atrightmargin", - ["fr"]="atrightmargin", + ["fr"]="enmargedroite", ["it"]="atrightmargin", ["nl"]="oprechtermarge", ["pe"]="درحاشیه‌راست", @@ -226,7 +231,7 @@ return { ["cs"]="odsazenizleva", ["de"]="rumpfweite", ["en"]="backspace", - ["fr"]="retourarriere", + ["fr"]="retourarrière", ["it"]="spaziodietro", ["nl"]="rugwit", ["pe"]="فاصله‌پشت", @@ -236,7 +241,7 @@ return { ["cs"]="cernalinka", ["de"]="rechteck", ["en"]="blackrule", - ["fr"]="lignenoire", + ["fr"]="traitepais", ["it"]="lineanera", ["nl"]="blokje", ["pe"]="خط‌سیاه", @@ -246,7 +251,7 @@ return { ["cs"]="cernelinky", ["de"]="rechtecke", ["en"]="blackrules", - ["fr"]="lignesnoires", + ["fr"]="traitsepais", ["it"]="lineenere", ["nl"]="blokjes", ["pe"]="خطهای‌سیاه", @@ -256,7 +261,7 @@ return { ["cs"]="preskoc", ["de"]="blanko", ["en"]="blank", - ["fr"]="vide", + ["fr"]="vierge", ["it"]="rigovuoto", ["nl"]="blanko", ["pe"]="خالی", @@ -276,7 +281,7 @@ return { ["cs"]="vzdalenostspodku", ["de"]="abstandunten", ["en"]="bottomdistance", - ["fr"]="distanceinf", + ["fr"]="distancebas", ["it"]="distanzafondo", ["nl"]="onderafstand", ["pe"]="فاصله‌پایین", @@ -286,7 +291,7 @@ return { ["cs"]="vyskaspodku", ["de"]="hoeheunten", ["en"]="bottomheight", - ["fr"]="hauteurinf", + ["fr"]="hauteurbas", ["it"]="altezzafondo", ["nl"]="onderhoogte", ["pe"]="ارتفاع‌پایین", @@ -296,7 +301,7 @@ return { ["cs"]="bottomspace", ["de"]="bottomspace", ["en"]="bottomspace", - ["fr"]="espaceinf", + ["fr"]="espacebas", ["it"]="spaziofondo", ["nl"]="bodemwit", ["pe"]="فضای‌پایین", @@ -306,7 +311,7 @@ return { ["cs"]="spodek", ["de"]="but", ["en"]="but", - ["fr"]="but", + ["fr"]="mais", ["it"]="fondo", ["nl"]="but", ["pe"]="اما", @@ -326,7 +331,7 @@ return { ["cs"]="bypassblocks", ["de"]="bypassblocks", ["en"]="bypassblocks", - ["fr"]="sauteblocs", + ["fr"]="eviteblocs", ["it"]="saltablocchi", ["nl"]="passeerblokken", ["pe"]="عبوربلوکها", @@ -366,7 +371,7 @@ return { ["cs"]="orez", ["de"]="ausschnitt", ["en"]="clip", - ["fr"]="clip", + ["fr"]="decouper", ["it"]="clip", ["nl"]="clip", ["pe"]="گیره", @@ -376,7 +381,7 @@ return { ["cs"]="klonujpole", ["de"]="klonierefeld", ["en"]="clonefield", - ["fr"]="clonechamp", + ["fr"]="clonerchamp", ["it"]="clonacampo", ["nl"]="kloonveld", ["pe"]="میدان‌شبیه‌سازی", @@ -426,7 +431,7 @@ return { ["cs"]="porovnejskupinubarev", ["de"]="vergleichefarbengruppe", ["en"]="comparecolorgroup", - ["fr"]="comparegroupecouleur", + ["fr"]="comparergroupecouleur", ["it"]="confrontagruppocolori", ["nl"]="vergelijkkleurgroep", ["pe"]="مقایسه‌گروه‌رنگ", @@ -436,7 +441,7 @@ return { ["cs"]="porovnejpaletu", ["de"]="vergleichepalette", ["en"]="comparepalet", - ["fr"]="comparepalette", + ["fr"]="comparerpalette", ["it"]="confrontatavolozza", ["nl"]="vergelijkpalet", ["pe"]="لوح‌مقایسه", @@ -446,7 +451,7 @@ return { ["cs"]="completepagenumber", ["de"]="completepagenumber", ["en"]="completepagenumber", - ["fr"]="completenumeropage", + ["fr"]="numeropagecomplet", ["it"]="numeropaginacompleto", ["nl"]="volledigepaginanummer", ["pe"]="شماره‌صفحه‌کامل", @@ -456,7 +461,7 @@ return { ["cs"]="completeregister", ["de"]="completeregister", ["en"]="completeregister", - ["fr"]="completeregistre", + ["fr"]="registrecomplet", ["it"]="completeregister", ["nl"]="volledigregister", ["pe"]="ثبت‌کامل", @@ -476,7 +481,7 @@ return { ["cs"]="konvertujcislo", ["de"]="konvertierezahl", ["en"]="convertnumber", - ["fr"]="convertitnumero", + ["fr"]="convertirnumero", ["it"]="convertinumero", ["nl"]="converteernummer", ["pe"]="شماره‌مبدل", @@ -486,7 +491,7 @@ return { ["cs"]="kopirujpole", ["de"]="kopierefeld", ["en"]="copyfield", - ["fr"]="copitchamp", + ["fr"]="copierchamp", ["it"]="copiacampo", ["nl"]="copieerveld", ["pe"]="میدان‌کپی", @@ -496,7 +501,7 @@ return { ["cs"]="korekcebilehomista", ["de"]="korrigierezwischenraum", ["en"]="correctwhitespace", - ["fr"]="corrigeespaceblanc", + ["fr"]="corrigerespaceblanc", ["it"]="correggispaziobianco", ["nl"]="corrigeerwitruimte", ["pe"]="فضای‌سفیدصحیح", @@ -526,7 +531,7 @@ return { ["cs"]="parovastrana", ["de"]="doppelseite", ["en"]="couplepage", - ["fr"]="pagedouble", + ["fr"]="couplepage", ["it"]="accoppiapagina", ["nl"]="koppelpagina", ["pe"]="صفحه‌زوج", @@ -576,7 +581,7 @@ return { ["cs"]="aktualnicislonadpisu", ["de"]="heutigeskopfnummer", ["en"]="currentheadnumber", - ["fr"]="numerotetecourant", + ["fr"]="numerotetecourante", ["it"]="numerotestacorrente", ["nl"]="huidigekopnummer", ["pe"]="شماره‌سرجاری", @@ -586,7 +591,7 @@ return { ["cs"]="cutspace", ["de"]="cutspace", ["en"]="cutspace", - ["fr"]="cutspace", + ["fr"]="espacecoupe", ["it"]="cutspace", ["nl"]="snijwit", ["pe"]="فضای‌برش", @@ -626,7 +631,7 @@ return { ["cs"]="definuj", ["de"]="definieren", ["en"]="define", - ["fr"]="definit", + ["fr"]="définir", ["it"]="definisci", ["nl"]="definieer", ["pe"]="تعریف", @@ -636,7 +641,7 @@ return { ["cs"]="definujakcent", ["de"]="definiereakzent", ["en"]="defineaccent", - ["fr"]="definitaccent", + ["fr"]="définiraccent", ["it"]="definisciaccento", ["nl"]="definieeraccent", ["pe"]="تعریف‌لهجه", @@ -646,7 +651,7 @@ return { ["cs"]="definujpreskok", ["de"]="definiereblanko", ["en"]="defineblank", - ["fr"]="definitvide", + ["fr"]="définirvierge", ["it"]="definiscirigovuoto", ["nl"]="definieerblanko", ["pe"]="تعریف‌خالی", @@ -656,7 +661,7 @@ return { ["cs"]="definujblok", ["de"]="definiereblock", ["en"]="defineblock", - ["fr"]="definitbloc", + ["fr"]="définirbloc", ["it"]="definisciblocco", ["nl"]="definieerblok", ["pe"]="تعریف‌بلوک", @@ -666,7 +671,7 @@ return { ["cs"]="definujzakladnifont", ["de"]="definierefliesstext", ["en"]="definebodyfont", - ["fr"]="definitpolicecorps", + ["fr"]="définirpolicedecorps", ["it"]="definiscifontdeltesto", ["nl"]="definieerkorps", ["pe"]="تعریف‌قلم‌متن", @@ -676,7 +681,7 @@ return { ["cs"]="definujprostredizakladnihofontu", ["de"]="definierefliesstextumgebung", ["en"]="definebodyfontenvironment", - ["fr"]="definitenvironnementpolicecorps", + ["fr"]="définirenvironnementpolicedecorps", ["it"]="definisciambientefontdeltesto", ["nl"]="definieerkorpsomgeving", ["pe"]="تعریف‌محیط‌قلم‌بدنه", @@ -686,7 +691,7 @@ return { ["cs"]="definujbuffer", ["de"]="definierepuffer", ["en"]="definebuffer", - ["fr"]="definitbuffer", + ["fr"]="définirtampon", ["it"]="definiscibuffer", ["nl"]="definieerbuffer", ["pe"]="تعریف‌بافر", @@ -696,7 +701,7 @@ return { ["cs"]="definujznak", ["de"]="definierezeichen", ["en"]="definecharacter", - ["fr"]="definicaractere", + ["fr"]="définircaractere", ["it"]="definiscicarattere", ["nl"]="definieerkarakter", ["pe"]="تعریف‌حرف", @@ -706,7 +711,7 @@ return { ["cs"]="definujbarvu", ["de"]="definierefarbe", ["en"]="definecolor", - ["fr"]="definitcouleur", + ["fr"]="définircouleur", ["it"]="definiscicolore", ["nl"]="definieerkleur", ["pe"]="تعریف‌رنگ", @@ -716,7 +721,7 @@ return { ["cs"]="definujskupinubarev", ["de"]="definierefarbengruppe", ["en"]="definecolorgroup", - ["fr"]="definitgroupecouleur", + ["fr"]="définirgroupecouleur", ["it"]="definiscigruppocolori", ["nl"]="definieerkleurgroep", ["pe"]="تعریف‌گروه‌رنگ", @@ -726,7 +731,7 @@ return { ["cs"]="definecolumnbreak", ["de"]="definecolumnbreak", ["en"]="definecolumnbreak", - ["fr"]="definitsautdecolonne", + ["fr"]="définirsautdecolonne", ["it"]="definecolumnbreak", ["nl"]="definieerkolomovergang", ["pe"]="تعریف‌شکستن‌ستون", @@ -736,7 +741,7 @@ return { ["cs"]="definecolumnset", ["de"]="definecolumnset", ["en"]="definecolumnset", - ["fr"]="definitjeucolonne", + ["fr"]="définirjeucolonnes", ["it"]="definiscigruppocolonne", ["nl"]="definieerkolomgroep", ["pe"]="تعریف‌مجموعه‌ستون", @@ -746,7 +751,7 @@ return { ["cs"]="definecombination", ["de"]="definecombination", ["en"]="definecombination", - ["fr"]="definecombination", + ["fr"]="définircombinaison", ["it"]="definecombination", ["nl"]="definieercombinatie", ["pe"]="تعریف‌ترکیب", @@ -756,7 +761,7 @@ return { ["cs"]="definujkombinovanyseznam", ["de"]="definierezusammengestellteliste", ["en"]="definecombinedlist", - ["fr"]="definitlisteimbriquee", + ["fr"]="définirlistecombinee", ["it"]="definiscielencocombinato", ["nl"]="definieersamengesteldelijst", ["pe"]="تعریف‌لیست‌ترکیبی", @@ -766,7 +771,7 @@ return { ["cs"]="definujprikaz", ["de"]="definierebefehl", ["en"]="definecommand", - ["fr"]="definitcommande", + ["fr"]="définircommande", ["it"]="definiscicomando", ["nl"]="definieercommando", ["pe"]="تعریف‌فرمان", @@ -776,7 +781,7 @@ return { ["cs"]="definujkonverzi", ["de"]="definierekonversion", ["en"]="defineconversion", - ["fr"]="definitconversion", + ["fr"]="définirconversion", ["it"]="definisciconversione", ["nl"]="definieerconversie", ["pe"]="تعریف‌تبدیل", @@ -786,7 +791,7 @@ return { ["cs"]="definujpopis", ["de"]="definierebeschreibung", ["en"]="definedescription", - ["fr"]="definitdescription", + ["fr"]="définirdescription", ["it"]="definiscidescrizione", ["nl"]="doordefinieren", ["pe"]="تعریف‌شرح", @@ -796,7 +801,7 @@ return { ["cs"]="definujvycet", ["de"]="definierenummerierung", ["en"]="defineenumeration", - ["fr"]="definitenumeration", + ["fr"]="définirénumération", ["it"]="definiscienumerazione", ["nl"]="doornummeren", ["pe"]="تعریف‌شماره‌بندی", @@ -806,7 +811,7 @@ return { ["cs"]="definujpole", ["de"]="definierefeld", ["en"]="definefield", - ["fr"]="definitchamp", + ["fr"]="définirchamp", ["it"]="definiscicampo", ["nl"]="definieerveld", ["pe"]="تعریف‌میدان", @@ -816,7 +821,7 @@ return { ["cs"]="definujzasobnikpoli", ["de"]="definierefeldstapel", ["en"]="definefieldstack", - ["fr"]="definitpilechamp", + ["fr"]="définirpilechamp", ["it"]="definiscistackcampi", ["nl"]="definieerveldstapel", ["pe"]="تعریف‌توده‌میدان", @@ -826,7 +831,7 @@ return { ["cs"]="definujobrazeksymbol", ["de"]="definiereabbsymbol", ["en"]="definefiguresymbol", - ["fr"]="definitsymbolefigure", + ["fr"]="définirfiguresymbole", ["it"]="definiscifigurasimbolo", ["nl"]="definieerfiguursymbool", ["pe"]="تعریف‌نمادشکل", @@ -836,7 +841,7 @@ return { ["cs"]="definujplvouciobjekt", ["de"]="definieregleitobjekt", ["en"]="definefloat", - ["fr"]="definitflottant", + ["fr"]="définirflottant", ["it"]="definiscioggettomobile", ["nl"]="definieerplaatsblok", ["pe"]="تعریف‌شناور", @@ -846,7 +851,7 @@ return { ["cs"]="definujfont", ["de"]="definiereschrift", ["en"]="definefont", - ["fr"]="definitpolice", + ["fr"]="définirpolice", ["it"]="definiscifont", ["nl"]="definieerfont", ["pe"]="تعریف‌قلم", @@ -856,7 +861,7 @@ return { ["cs"]="definujstylfontu", ["de"]="definiereschriftstil", ["en"]="definefontstyle", - ["fr"]="definitstylepolice", + ["fr"]="définirstylepolice", ["it"]="definiscistilefont", ["nl"]="definieerfontstijl", ["pe"]="تعریف‌سبک‌قلم", @@ -866,7 +871,7 @@ return { ["cs"]="definujsynonumumfontu", ["de"]="defineschriftsynonym", ["en"]="definefontsynonym", - ["fr"]="definitsynonymepolice", + ["fr"]="définirsynonymepolice", ["it"]="definiscisinonimofont", ["nl"]="definieerfontsynoniem", ["pe"]="تعریف‌مترادف‌قلم", @@ -876,7 +881,7 @@ return { ["cs"]="definujoramovani", ["de"]="definiereumrahmt", ["en"]="defineframed", - ["fr"]="defineframed", + ["fr"]="définirencadre", ["it"]="definisciincorniciato", ["nl"]="definieeromlijnd", ["pe"]="تعریف‌قالبی", @@ -886,7 +891,7 @@ return { ["cs"]="definujoramovanytext", ["de"]="definiereumrahmtertext", ["en"]="defineframedtext", - ["fr"]="defineframedtext", + ["fr"]="définirtexteencadre", ["it"]="definiscitestoincorniciato", ["nl"]="definieerkadertekst", ["pe"]="تعریف‌متن‌قالبی", @@ -896,7 +901,7 @@ return { ["cs"]="definujhbox", ["de"]="definierehbox", ["en"]="definehbox", - ["fr"]="definithbox", + ["fr"]="définirhbox", ["it"]="definiscihbox", ["nl"]="definieerhbox", ["pe"]="تعریف‌جعبه‌‌افقی", @@ -906,7 +911,7 @@ return { ["cs"]="definujnadpis", ["de"]="definiereueberschrift", ["en"]="definehead", - ["fr"]="definittete", + ["fr"]="définirtete", ["it"]="definiscitesta", ["nl"]="definieerkop", ["pe"]="تعریف‌سر", @@ -914,13 +919,14 @@ return { }, ["defineindentedtext"]={ ["en"]="defineindentedtext", + ["fr"]="définirtexteindente", ["nl"]="definieeringesprongentext", }, ["defineinmargin"]={ ["cs"]="defineinmargin", ["de"]="defineinmargin", ["en"]="defineinmargin", - ["fr"]="definitdansmarge", + ["fr"]="définirdansmarge", ["it"]="defineinmargin", ["nl"]="definieerinmarge", ["pe"]="تعریف‌درون‌حاشیه", @@ -930,7 +936,7 @@ return { ["cs"]="definujinterakcnimenu", ["de"]="definiereinteraktionsmenue", ["en"]="defineinteractionmenu", - ["fr"]="definitmenuinteraction", + ["fr"]="définirmenuinteraction", ["it"]="definiscimenuinterazione", ["nl"]="definieerinteractiemenu", ["pe"]="تعریف‌منوی‌پانل", @@ -940,7 +946,7 @@ return { ["cs"]="defineitemgroup", ["de"]="defineitemgroup", ["en"]="defineitemgroup", - ["fr"]="defineitemgroup", + ["fr"]="définirgroupedéléments", ["it"]="defineitemgroup", ["nl"]="definieeritemgroep", ["pe"]="تعریف‌گروه‌آیتم", @@ -950,7 +956,7 @@ return { ["cs"]="definujpopisek", ["de"]="definierelabel", ["en"]="definelabel", - ["fr"]="definitetiquette", + ["fr"]="définiretiquette", ["it"]="definiscietichetta", ["nl"]="doorlabelen", ["pe"]="تعریف‌برچسب", @@ -960,7 +966,7 @@ return { ["cs"]="definelayer", ["de"]="definelayer", ["en"]="definelayer", - ["fr"]="definitcalque", + ["fr"]="définircalque", ["it"]="definelayer", ["nl"]="definieerlayer", ["pe"]="تعریف‌لایه", @@ -970,7 +976,7 @@ return { ["cs"]="definelayout", ["de"]="definelayout", ["en"]="definelayout", - ["fr"]="definitdisposition", + ["fr"]="définirmiseenpage", ["it"]="definiscilayout", ["nl"]="definieerlayout", ["pe"]="تعریف‌طرح‌بندی", @@ -980,7 +986,7 @@ return { ["cs"]="definujseznam", ["de"]="definiereliste", ["en"]="definelist", - ["fr"]="definitliste", + ["fr"]="définirliste", ["it"]="definiscielenco", ["nl"]="definieerlijst", ["pe"]="تعریف‌لیست", @@ -990,7 +996,7 @@ return { ["cs"]="definujlogo", ["de"]="definierelogo", ["en"]="definelogo", - ["fr"]="definitlogo", + ["fr"]="définirlogo", ["it"]="definiscilogo", ["nl"]="definieerbeeldmerk", ["pe"]="تعریف‌آرم", @@ -1000,7 +1006,7 @@ return { ["cs"]="definujhlavnipole", ["de"]="definierehauptfeld", ["en"]="definemainfield", - ["fr"]="definitchampprincipal", + ["fr"]="définirchampprincipal", ["it"]="definiscicampoprincipale", ["nl"]="definieerhoofdveld", ["pe"]="تعریف‌میدان‌اصلی", @@ -1010,7 +1016,7 @@ return { ["cs"]="definujupravu", ["de"]="definiereumbruch", ["en"]="definemakeup", - ["fr"]="definitmakeup", + ["fr"]="définircomposition", ["it"]="definiscimakeup", ["nl"]="definieeropmaak", ["pe"]="تعریف‌آرایش", @@ -1020,7 +1026,7 @@ return { ["cs"]="definujznaceni", ["de"]="definierebeschriftung", ["en"]="definemarking", - ["fr"]="definitmarquage", + ["fr"]="définirmarquage", ["it"]="definiscimarcatura", ["nl"]="definieermarkering", ["pe"]="تعریف‌نشانه‌گذاری", @@ -1030,7 +1036,7 @@ return { ["cs"]="definemathalignment", ["de"]="definemathalignment", ["en"]="definemathalignment", - ["fr"]="definemathalignment", + ["fr"]="définiralignementmath", ["it"]="definemathalignment", ["nl"]="definieerwiskundeuitlijnen", ["pe"]="تعریف‌تنظیم‌ریاضی", @@ -1040,7 +1046,7 @@ return { ["cs"]="definujvystup", ["de"]="defineoutput", ["en"]="defineoutput", - ["fr"]="definitsortie", + ["fr"]="définirsortie", ["it"]="definiscioutput", ["nl"]="definieeruitvoer", ["pe"]="تعریف‌خروجی", @@ -1050,7 +1056,7 @@ return { ["cs"]="definujprekryv", ["de"]="definiereoverlay", ["en"]="defineoverlay", - ["fr"]="definitrevetement", + ["fr"]="définirsuperposition", ["it"]="definiscisovrapposizione", ["nl"]="definieeroverlay", ["pe"]="تعریف‌پوشش", @@ -1060,7 +1066,7 @@ return { ["cs"]="definepagebreak", ["de"]="definepagebreak", ["en"]="definepagebreak", - ["fr"]="definitsautdepage", + ["fr"]="définirsautdepage", ["it"]="definepagebreak", ["nl"]="definieerpaginaovergang", ["pe"]="تعریف‌شکست‌صفحه", @@ -1070,7 +1076,7 @@ return { ["cs"]="definujpaletu", ["de"]="definierepalette", ["en"]="definepalet", - ["fr"]="definitpalette", + ["fr"]="définirpalette", ["it"]="definiscitavolozza", ["nl"]="definieerpalet", ["pe"]="تعریف‌لوح", @@ -1080,7 +1086,7 @@ return { ["cs"]="definujvelikostpapiru", ["de"]="definierepapierformat", ["en"]="definepapersize", - ["fr"]="definittaillepapier", + ["fr"]="définirtaillepapier", ["it"]="definiscidimensionicarta", ["nl"]="definieerpapierformaat", ["pe"]="تعریف‌اندازه‌برگ", @@ -1090,7 +1096,7 @@ return { ["cs"]="definujodstavce", ["de"]="definiereabsaetze", ["en"]="defineparagraphs", - ["fr"]="definitparagraphes", + ["fr"]="définirparagraphes", ["it"]="definiscicapoversi", ["nl"]="definieeralineas", ["pe"]="تعریف‌پاراگرافها", @@ -1100,7 +1106,7 @@ return { ["cs"]="defineplacement", ["de"]="defineplacement", ["en"]="defineplacement", - ["fr"]="defineplacement", + ["fr"]="définirplacement", ["it"]="defineplacement", ["nl"]="definieerplaats", ["pe"]="تعریف‌جانشانی", @@ -1110,7 +1116,7 @@ return { ["cs"]="definujprofil", ["de"]="definiereprofil", ["en"]="defineprofile", - ["fr"]="definitprofil", + ["fr"]="définirprofil", ["it"]="definisciprofilo", ["nl"]="definieerprofiel", ["pe"]="تعریف‌پروفایل", @@ -1120,7 +1126,7 @@ return { ["cs"]="definujprogram", ["de"]="definiereprogramme", ["en"]="defineprogram", - ["fr"]="definitprogramme", + ["fr"]="définirprogramme", ["it"]="definisciprogramma", ["nl"]="definieerprogramma", ["pe"]="تعریف‌برنامه", @@ -1130,7 +1136,7 @@ return { ["cs"]="definerawfont", ["de"]="definerawfont", ["en"]="definerawfont", - ["fr"]="definitpolicebrute", + ["fr"]="définirpolicebrute", ["it"]="definiscifontgrezzo", ["nl"]="definerawfont", ["pe"]="تعریف‌قلم‌خام", @@ -1140,7 +1146,7 @@ return { ["cs"]="definujodkaz", ["de"]="definierereferenz", ["en"]="definereference", - ["fr"]="definitreference", + ["fr"]="définirreference", ["it"]="definisciriferimento", ["nl"]="definieerreferentie", ["pe"]="تعریف‌مرجع", @@ -1150,7 +1156,7 @@ return { ["cs"]="definujformatodkazu", ["de"]="definierereferenzformat", ["en"]="definereferenceformat", - ["fr"]="definitformatreference", + ["fr"]="définirformatrereference", ["it"]="definisciformatoriferimento", ["nl"]="definieerreferentieformaat", ["pe"]="تعریف‌شمایل‌مرجع", @@ -1160,7 +1166,7 @@ return { ["cs"]="definujseznamodkazu", ["de"]="definierereferenzliste", ["en"]="definereferencelist", - ["fr"]="definitlistereference", + ["fr"]="définirlistereference", ["it"]="definiscilistariferimenti", ["nl"]="definieerreferentielijst", ["pe"]="تعریف‌لیست‌مرجع", @@ -1170,7 +1176,7 @@ return { ["cs"]="definujrejstrik", ["de"]="definiereregister", ["en"]="defineregister", - ["fr"]="definitregistre", + ["fr"]="définirregistre", ["it"]="definisciregistro", ["nl"]="definieerregister", ["pe"]="تعریف‌ثبت", @@ -1180,7 +1186,7 @@ return { ["cs"]="definerule", ["de"]="definerule", ["en"]="definerule", - ["fr"]="definitregle", + ["fr"]="définirtrait", ["it"]="definiscilinea", ["nl"]="definieerlijn", ["pe"]="تعریف‌خط‌حائل", @@ -1190,7 +1196,7 @@ return { ["cs"]="definujsekci", ["de"]="definiereabschnitt", ["en"]="definesection", - ["fr"]="definitsection", + ["fr"]="définirsection", ["it"]="definiscisezione", ["nl"]="definieersectie", ["pe"]="تعریف‌بخش", @@ -1200,7 +1206,7 @@ return { ["cs"]="definujbloksekce", ["de"]="definiereabschnittsblock", ["en"]="definesectionblock", - ["fr"]="definitblocsection", + ["fr"]="définirblocsection", ["it"]="definiscibloccosezione", ["nl"]="definieersectieblok", ["pe"]="تعریف‌بلوک‌بخش", @@ -1210,7 +1216,7 @@ return { ["cs"]="definujtrideni", ["de"]="definieresortieren", ["en"]="definesorting", - ["fr"]="definittri", + ["fr"]="définirtri", ["it"]="definisciordinamento", ["nl"]="definieersorteren", ["pe"]="تعریف‌ترتیب", @@ -1220,7 +1226,7 @@ return { ["cs"]="definujstartstop", ["de"]="definierestartstop", ["en"]="definestartstop", - ["fr"]="definitdemarrestoppe", + ["fr"]="définirdébutfin", ["it"]="definisciiniziatermina", ["nl"]="definieerstartstop", ["pe"]="تعریف‌شروع‌پایان", @@ -1230,7 +1236,7 @@ return { ["cs"]="definujstyl", ["de"]="definierestil", ["en"]="definestyle", - ["fr"]="definitstyle", + ["fr"]="définirstyle", ["it"]="definiscistile", ["nl"]="definieerletter", ["pe"]="تعریف‌سبک", @@ -1240,7 +1246,7 @@ return { ["cs"]="definujpodpole", ["de"]="definieresubfeld", ["en"]="definesubfield", - ["fr"]="definitsouschamp", + ["fr"]="définirsouschamp", ["it"]="definiscisottocampo", ["nl"]="definieersubveld", ["pe"]="تعریف‌زیرمیدان", @@ -1250,7 +1256,7 @@ return { ["cs"]="definujsymbol", ["de"]="definieresymbol", ["en"]="definesymbol", - ["fr"]="definitsymbole", + ["fr"]="définirsymbole", ["it"]="definiscisimbolo", ["nl"]="definieersymbool", ["pe"]="تعریف‌نماد", @@ -1260,7 +1266,7 @@ return { ["cs"]="definujsynonyma", ["de"]="definieresynonyme", ["en"]="definesynonyms", - ["fr"]="definitsynonymes", + ["fr"]="définirsynonymes", ["it"]="definiscisinonimi", ["nl"]="definieersynoniemen", ["pe"]="تعریف‌مترادفها", @@ -1270,7 +1276,7 @@ return { ["cs"]="definujsablonutabulky", ["de"]="definieretabellenvorlage", ["en"]="definetabletemplate", - ["fr"]="definittrametableau", + ["fr"]="définirgabarittable", ["it"]="definiscimodellotabella", ["nl"]="definieertabelvorm", ["pe"]="تعریف‌الگوی‌جدول", @@ -1280,7 +1286,7 @@ return { ["cs"]="definujtabelaci", ["de"]="definieretabulator", ["en"]="definetabulate", - ["fr"]="definittabulation", + ["fr"]="définirtabulation", ["it"]="definiscitabulato", ["nl"]="definieertabulatie", ["pe"]="تعریف‌جدول‌بندی", @@ -1290,7 +1296,7 @@ return { ["cs"]="definujtext", ["de"]="definieretext", ["en"]="definetext", - ["fr"]="definittexte", + ["fr"]="définirtexte", ["it"]="definiscitesto", ["nl"]="definieertekst", ["pe"]="تعریف‌متن", @@ -1298,13 +1304,14 @@ return { }, ["definetextbackground"]={ ["en"]="definetextbackground", + ["fr"]="définirtextearriereplan", ["nl"]="definieertekstachtergrond", }, ["definetextposition"]={ ["cs"]="definetextposition", ["de"]="definetextposition", ["en"]="definetextposition", - ["fr"]="definitpositiontexte", + ["fr"]="définirpositiontexte", ["it"]="definisciposizionetesto", ["nl"]="definieertekstpositie", ["pe"]="تعریف‌مکان‌متن", @@ -1314,7 +1321,7 @@ return { ["cs"]="definetextvariable", ["de"]="definetextvariable", ["en"]="definetextvariable", - ["fr"]="definitvariabletexte", + ["fr"]="définirvariabletexte", ["it"]="definiscivariabiletesto", ["nl"]="definieertekstvariabele", ["pe"]="تعریف‌متغیرمتن", @@ -1324,7 +1331,7 @@ return { ["cs"]="definetype", ["de"]="definetype", ["en"]="definetype", - ["fr"]="definittype", + ["fr"]="définirtranscrire", ["it"]="definiscitype", ["nl"]="definieertype", ["pe"]="تعریف‌تایپ", @@ -1334,7 +1341,7 @@ return { ["cs"]="definujopis", ["de"]="definieretippen", ["en"]="definetyping", - ["fr"]="definitdactylo", + ["fr"]="définirtranscription", ["it"]="definiscityping", ["nl"]="definieertypen", ["pe"]="تعریف‌تایپ‌کردن", @@ -1344,7 +1351,7 @@ return { ["cs"]="definujverzi", ["de"]="definiereversion", ["en"]="defineversion", - ["fr"]="definitversion", + ["fr"]="définirversion", ["it"]="definisciversion", ["nl"]="definieerversie", ["pe"]="تعریف‌نسخه", @@ -1354,7 +1361,7 @@ return { ["cs"]="stanovcislonadpisu", ["de"]="bestimmekopfnummer", ["en"]="determineheadnumber", - ["fr"]="determinenumerotete", + ["fr"]="determinernumerotete", ["it"]="determinanumerotesta", ["nl"]="bepaalkopnummer", ["pe"]="تعیین‌شماره‌سر", @@ -1364,7 +1371,7 @@ return { ["cs"]="stanovcharakteristickuseznamu", ["de"]="bestimmelistencharakeristika", ["en"]="determinelistcharacteristics", - ["fr"]="determinecaracteristiqueliste", + ["fr"]="determinercaracteristiquesliste", ["it"]="determinacarattersticheelenco", ["nl"]="bepaallijstkenmerken", ["pe"]="تعیین‌مشخصات‌لیست", @@ -1374,7 +1381,7 @@ return { ["cs"]="urcicharakteristikurejstriku", ["de"]="bestimmeregistercharakteristika", ["en"]="determineregistercharacteristics", - ["fr"]="determinecaracteristiquesregistre", + ["fr"]="determinercaracteristiquesregistre", ["it"]="determinacaratteristicheregistro", ["nl"]="bepaalregisterkenmerken", ["pe"]="تعیین‌مشخصات‌ثبت", @@ -1394,7 +1401,7 @@ return { ["cs"]="zablokujinterakcnimenu", ["de"]="inaktiviereinteraktionsmenue", ["en"]="disableinteractionmenu", - ["fr"]="inhibemenuinteraction", + ["fr"]="desactivermenuinteraction", ["it"]="disabilitamenuinterazione", ["nl"]="blokkeerinteractiemenu", ["pe"]="ازکارانداختن‌منوی‌پانل", @@ -1414,7 +1421,7 @@ return { ["cs"]="zadnytest", ["de"]="keintest", ["en"]="donttest", - ["fr"]="sanstest", + ["fr"]="sanstester", ["it"]="notest", ["nl"]="geentest", ["pe"]="امتحان‌نکن", @@ -1444,7 +1451,7 @@ return { ["cs"]="emptylines", ["de"]="emptylines", ["en"]="emptylines", - ["fr"]="emptylines", + ["fr"]="lignesvide", ["it"]="emptylines", ["nl"]="legeregels", ["pe"]="خطها‌خالی", @@ -1454,7 +1461,7 @@ return { ["cs"]="prostredi", ["de"]="umgebung", ["en"]="environment", - ["fr"]="environement", + ["fr"]="environnement", ["it"]="ambiente", ["nl"]="omgeving", ["pe"]="محیط", @@ -1504,7 +1511,7 @@ return { ["cs"]="vyplnovepole", ["de"]="ausfuellfeld", ["en"]="fillinfield", - ["fr"]="remplitchamp", + ["fr"]="champarenseigner", ["it"]="camporiempimento", ["nl"]="invulveld", ["pe"]="درج‌درمیدان", @@ -1514,7 +1521,7 @@ return { ["cs"]="vyplnovyradek", ["de"]="gefuelltezeile", ["en"]="fillinline", - ["fr"]="remplitligne", + ["fr"]="lignearenseigner", ["it"]="rigariempimento", ["nl"]="invulregel", ["pe"]="درج‌درخط", @@ -1524,7 +1531,7 @@ return { ["cs"]="vyplnovelinky", ["de"]="gefuelltesrechteck", ["en"]="fillinrules", - ["fr"]="remplitlignesreglees", + ["fr"]="traitsarenseigner", ["it"]="lineeriempimento", ["nl"]="invullijnen", ["pe"]="درج‌درخطها", @@ -1534,7 +1541,7 @@ return { ["cs"]="vyplnenytext", ["de"]="ausfuelltext", ["en"]="fillintext", - ["fr"]="remplittexte", + ["fr"]="textearenseigner", ["it"]="testoriempimento", ["nl"]="invultekst", ["pe"]="درج‌درمتن", @@ -1544,7 +1551,7 @@ return { ["cs"]="prizpusobivepole", ["de"]="passendfeld", ["en"]="fitfield", - ["fr"]="ajustechamp", + ["fr"]="adapterchamp", ["it"]="adattacampo", ["nl"]="passendveld", ["pe"]="پرکردن‌میدان", @@ -1574,7 +1581,7 @@ return { ["cs"]="dodrzujprofil", ["de"]="folgeprofil", ["en"]="followprofile", - ["fr"]="suivantprofil", + ["fr"]="suivreprofile", ["it"]="seguiprofilo", ["nl"]="volgprofiel", ["pe"]="پیروی‌پروفایل", @@ -1584,7 +1591,7 @@ return { ["cs"]="dodrzujverziprofilu", ["de"]="folgeprofilversion", ["en"]="followprofileversion", - ["fr"]="suivantversionprofil", + ["fr"]="suivreversionprofil", ["it"]="seguiversioneprofilo", ["nl"]="volgprofielversie", ["pe"]="پیروی‌نسخه‌پروفایل", @@ -1594,7 +1601,7 @@ return { ["cs"]="dodrzujverzi", ["de"]="folgeversion", ["en"]="followversion", - ["fr"]="suivantversion", + ["fr"]="suivreversion", ["it"]="seguiversione", ["nl"]="volgversie", ["pe"]="پیروی‌نسخه", @@ -1624,7 +1631,7 @@ return { ["cs"]="poznamkapodcarou", ["de"]="fussnote", ["en"]="footnote", - ["fr"]="notepdp", + ["fr"]="notebdp", ["it"]="notapdp", ["nl"]="voetnoot", ["pe"]="پانوشت", @@ -1634,7 +1641,7 @@ return { ["cs"]="footnotetext", ["de"]="footnotetext", ["en"]="footnotetext", - ["fr"]="textenotepdp", + ["fr"]="textenotebdp", ["it"]="testonotapdp", ["nl"]="voetnoottekst", ["pe"]="متن‌پانوشت", @@ -1644,7 +1651,7 @@ return { ["cs"]="forceblocks", ["de"]="forceblocks", ["en"]="forceblocks", - ["fr"]="forceblocs", + ["fr"]="forcerblocs", ["it"]="forzablocchi", ["nl"]="forceerblokken", ["pe"]="اجباربلوکها", @@ -1674,7 +1681,7 @@ return { ["cs"]="oramovani", ["de"]="umrahmt", ["en"]="framed", - ["fr"]="framed", + ["fr"]="encadre", ["it"]="incorniciato", ["nl"]="omlijnd", ["pe"]="قالبی", @@ -1694,7 +1701,7 @@ return { ["cs"]="ziskejbuffer", ["de"]="holepuffer", ["en"]="getbuffer", - ["fr"]="prendbuffer", + ["fr"]="obtenirtampon", ["it"]="prendibuffer", ["nl"]="haalbuffer", ["pe"]="دریافت‌بافر", @@ -1704,7 +1711,7 @@ return { ["cs"]="ziskejznaceni", ["de"]="holebeschriftung", ["en"]="getmarking", - ["fr"]="obtientmarquage", + ["fr"]="obtenirmarquage", ["it"]="prendimarcatura", ["nl"]="haalmarkering", ["pe"]="دریافت‌نشانه", @@ -1714,7 +1721,7 @@ return { ["cs"]="getnumber", ["de"]="getnumber", ["en"]="getnumber", - ["fr"]="getnumber", + ["fr"]="obtenirnumero", ["it"]="getnumber", ["nl"]="haalnummer", ["pe"]="دریافت‌شماره", @@ -1724,7 +1731,7 @@ return { ["cs"]="jdidolu", ["de"]="nachunten", ["en"]="godown", - ["fr"]="vaenbas", + ["fr"]="allerenbas", ["it"]="vaigiu", ["nl"]="omlaag", ["pe"]="بروپایین", @@ -1734,7 +1741,7 @@ return { ["cs"]="jdina", ["de"]="zu", ["en"]="goto", - ["fr"]="va", + ["fr"]="allera", ["it"]="vaia", ["nl"]="naar", ["pe"]="بروبه", @@ -1744,7 +1751,7 @@ return { ["cs"]="jdinabox", ["de"]="zurbox", ["en"]="gotobox", - ["fr"]="vaalaboite", + ["fr"]="alleraboite", ["it"]="vaiabox", ["nl"]="naarbox", ["pe"]="بروبه‌جعبه", @@ -1754,7 +1761,7 @@ return { ["cs"]="jdinastranu", ["de"]="zurseite", ["en"]="gotopage", - ["fr"]="vaalapage", + ["fr"]="allerapage", ["it"]="vaiapagina", ["nl"]="naarpagina", ["pe"]="بروبه‌صفحه", @@ -1794,7 +1801,7 @@ return { ["cs"]="vlasovalinka", ["de"]="haarlinie", ["en"]="hairline", - ["fr"]="ligneh", + ["fr"]="ligneavectrait", ["it"]="capello", ["nl"]="haarlijn", ["pe"]="خط‌مو", @@ -1804,7 +1811,7 @@ return { ["cs"]="nadpis", ["de"]="kopf", ["en"]="head", - ["fr"]="tete", + ["fr"]="tête", ["it"]="testa", ["nl"]="kop", ["pe"]="سر", @@ -1814,7 +1821,7 @@ return { ["cs"]="vzdalenostzahlavi", ["de"]="kopfzeilenabstand", ["en"]="headerdistance", - ["fr"]="distanceentete", + ["fr"]="distanceentête", ["it"]="distanzaintestazione", ["nl"]="hoofdafstand", ["pe"]="فاصله‌سربرگ", @@ -1824,7 +1831,7 @@ return { ["cs"]="vyskazahlavi", ["de"]="kopfzeilenhoehe", ["en"]="headerheight", - ["fr"]="hauteurentete", + ["fr"]="hauteurentête", ["it"]="altezzaintestazione", ["nl"]="hoofdhoogte", ["pe"]="ارتفاع‌سربرگ", @@ -1854,7 +1861,7 @@ return { ["cs"]="headsym", ["de"]="headsym", ["en"]="headsym", - ["fr"]="headsym", + ["fr"]="symtete", ["it"]="headsym", ["nl"]="kopsym", ["pe"]="نمادسر", @@ -1874,7 +1881,7 @@ return { ["cs"]="schovejbloky", ["de"]="verbergebloecke", ["en"]="hideblocks", - ["fr"]="cacheblocs", + ["fr"]="cacherblocs", ["it"]="nascondiblocchi", ["nl"]="verbergblokken", ["pe"]="بلوکها‌پنهان", @@ -1884,7 +1891,7 @@ return { ["cs"]="vysoky", ["de"]="hoch", ["en"]="high", - ["fr"]="haut", + ["fr"]="exposant", ["it"]="ap", ["nl"]="hoog", ["pe"]="بلند", @@ -1894,7 +1901,7 @@ return { ["cs"]="hl", ["de"]="hl", ["en"]="hl", - ["fr"]="hl", + ["fr"]="lh", ["it"]="hl", ["nl"]="hl", ["pe"]="خ‌ا", @@ -1904,7 +1911,7 @@ return { ["cs"]="immediatebetweenlist", ["de"]="immediatebetweenlist", ["en"]="immediatebetweenlist", - ["fr"]="immediatebetweenlist", + ["fr"]="immediatemententreliste", ["it"]="immediatebetweenlist", ["nl"]="directtussenlijst", ["pe"]="فوری‌بین‌لیست", @@ -1914,7 +1921,7 @@ return { ["cs"]="immediatetolist", ["de"]="immediatetolist", ["en"]="immediatetolist", - ["fr"]="immediatetolist", + ["fr"]="immediatementalister", ["it"]="immediatetolist", ["nl"]="directnaarlijst", ["pe"]="فوری‌به‌لیست", @@ -1934,7 +1941,7 @@ return { ["cs"]="zvysujicicislo", ["de"]="nummererhoehen", ["en"]="incrementnumber", - ["fr"]="incrementenumero", + ["fr"]="incrementernumero", ["it"]="incrementanumero", ["nl"]="verhoognummer", ["pe"]="شماره‌افزایش", @@ -1944,7 +1951,7 @@ return { ["cs"]="odsazovani", ["de"]="einziehen", ["en"]="indenting", - ["fr"]="composeenalinea", + ["fr"]="indentation", ["it"]="rientro", ["nl"]="inspringen", ["pe"]="تورفتگی", @@ -1954,7 +1961,7 @@ return { ["cs"]="zaramovani", ["de"]="imumriss", ["en"]="inframed", - ["fr"]="inframed", + ["fr"]="dansencadre", ["it"]="circondato", ["nl"]="inlijnd", ["pe"]="درقالبی", @@ -1964,7 +1971,7 @@ return { ["cs"]="plnezneni", ["de"]="volleswort", ["en"]="infull", - ["fr"]="infull", + ["fr"]="encomplet", ["it"]="perlungo", ["nl"]="voluit", ["pe"]="درپر", @@ -1974,7 +1981,7 @@ return { ["cs"]="ininner", ["de"]="ininner", ["en"]="ininner", - ["fr"]="ininner", + ["fr"]="dansinterieur", ["it"]="ininner", ["nl"]="inbinnen", ["pe"]="درداخلی", @@ -2014,7 +2021,7 @@ return { ["cs"]="vradku", ["de"]="inzeile", ["en"]="inline", - ["fr"]="alaligne", + ["fr"]="enligne", ["it"]="inriga", ["nl"]="inregel", ["pe"]="درخط", @@ -2034,7 +2041,7 @@ return { ["cs"]="mazaramovani", ["de"]="immaumrise", ["en"]="inmaframed", - ["fr"]="inmframed", + ["fr"]="dansencadremath", ["it"]="inmaframed", ["nl"]="inwilijnd", ["pe"]="inmframed", @@ -2044,7 +2051,7 @@ return { ["cs"]="inneredgedistance", ["de"]="inneredgedistance", ["en"]="inneredgedistance", - ["fr"]="inneredgedistance", + ["fr"]="distancebordinterieur", ["it"]="inneredgedistance", ["nl"]="binnenrandafstand", ["pe"]="فاصله‌لبه‌داخلی", @@ -2054,7 +2061,7 @@ return { ["cs"]="inneredgewidth", ["de"]="inneredgewidth", ["en"]="inneredgewidth", - ["fr"]="inneredgewidth", + ["fr"]="largeurbordinterieur", ["it"]="inneredgewidth", ["nl"]="binnenrandbreedte", ["pe"]="عرض‌لبه‌داخلی", @@ -2064,7 +2071,7 @@ return { ["cs"]="innermargindistance", ["de"]="innermargindistance", ["en"]="innermargindistance", - ["fr"]="innermargindistance", + ["fr"]="distancemargeinterieure", ["it"]="innermargindistance", ["nl"]="binnenmargeafstand", ["pe"]="فاصله‌حاشیه‌داخلی", @@ -2074,7 +2081,7 @@ return { ["cs"]="innermarginwidth", ["de"]="innermarginwidth", ["en"]="innermarginwidth", - ["fr"]="innermarginwidth", + ["fr"]="largeurmargeinterieure", ["it"]="innermarginwidth", ["nl"]="binnenmargebreedte", ["pe"]="عرض‌حاشیه‌داخلی", @@ -2094,7 +2101,7 @@ return { ["cs"]="inouter", ["de"]="inouter", ["en"]="inouter", - ["fr"]="inouter", + ["fr"]="dansexterieur", ["it"]="inouter", ["nl"]="inbuiten", ["pe"]="درخارجی", @@ -2134,7 +2141,7 @@ return { ["cs"]="instalacejazyka", ["de"]="installieresprache", ["en"]="installlanguage", - ["fr"]="installelangue", + ["fr"]="installerlangue", ["it"]="installalingua", ["nl"]="installeertaal", ["pe"]="نصب‌زبان", @@ -2174,7 +2181,7 @@ return { ["cs"]="polozka", ["de"]="pos", ["en"]="item", - ["fr"]="element", + ["fr"]="élément", ["it"]="elemento", ["nl"]="som", ["pe"]="آیتم", @@ -2184,7 +2191,7 @@ return { ["cs"]="polozky", ["de"]="posten", ["en"]="items", - ["fr"]="elements", + ["fr"]="éléments", ["it"]="elementi", ["nl"]="items", ["pe"]="آیتمها", @@ -2194,7 +2201,7 @@ return { ["cs"]="pol", ["de"]="its", ["en"]="its", - ["fr"]="el", + ["fr"]="els", ["it"]="el", ["nl"]="its", ["pe"]="its", @@ -2204,7 +2211,7 @@ return { ["cs"]="zachovejbloky", ["de"]="behaltebloecke", ["en"]="keepblocks", - ["fr"]="gardeblocs", + ["fr"]="conserverblocs", ["it"]="tieniblocchi", ["nl"]="handhaafblokken", ["pe"]="حفظ‌بلوکها", @@ -2234,7 +2241,7 @@ return { ["cs"]="textpopisku", ["de"]="labeltext", ["en"]="labeltext", - ["fr"]="labeltexte", + ["fr"]="texteetiquette", ["it"]="testoetichetta", ["nl"]="labeltekst", ["pe"]="متن‌برچسب", @@ -2310,6 +2317,11 @@ return { ["pe"]="پا", ["ro"]="leg", }, + ["linecorrection"]={ + ["en"]="linecorrection", + ["fr"]="correctionligne", + ["nl"]="regelcorrectie", + }, ["linewidth"]={ ["cs"]="tloustkacary", ["de"]="liniendicke", @@ -2334,7 +2346,7 @@ return { ["cs"]="delkaseznamu", ["de"]="listenlaenge", ["en"]="listlength", - ["fr"]="llongueurliste", + ["fr"]="longueurtexte", ["it"]="lunghezzaelenco", ["nl"]="lijstlengte", ["pe"]="طول‌لیست", @@ -2344,7 +2356,7 @@ return { ["cs"]="listsymbol", ["de"]="listsymbol", ["en"]="listsymbol", - ["fr"]="listesymbole", + ["fr"]="symboleliste", ["it"]="listsymbol", ["nl"]="lijstsymbool", ["pe"]="نمادلیست", @@ -2360,11 +2372,16 @@ return { ["pe"]="عرض‌لیست", ["ro"]="latimelista", }, + ["localfootnotes"]={ + ["en"]="localfootnotes", + ["fr"]="notesbdplocales", + ["nl"]="lokalevoetnoten", + }, ["logfields"]={ ["cs"]="zaznamovepole", ["de"]="registrierefelder", ["en"]="logfields", - ["fr"]="logchamp", + ["fr"]="logchamps", ["it"]="logcampi", ["nl"]="registreervelden", ["pe"]="میدانهای‌گزارش", @@ -2374,7 +2391,7 @@ return { ["cs"]="nivy", ["de"]="tiho", ["en"]="lohi", - ["fr"]="baha", + ["fr"]="inex", ["it"]="pedap", ["nl"]="laho", ["pe"]="پابا", @@ -2384,7 +2401,7 @@ return { ["cs"]="nizky", ["de"]="tief", ["en"]="low", - ["fr"]="bas", + ["fr"]="indice", ["it"]="ped", ["nl"]="laag", ["pe"]="پایین", @@ -2414,7 +2431,7 @@ return { ["cs"]="vyskasazby", ["de"]="satzhoehe", ["en"]="makeupheight", - ["fr"]="hauteurmakeup", + ["fr"]="hauteurcomposition", ["it"]="altezzamakeup", ["nl"]="zethoogte", ["pe"]="ارتفاع‌آرایش", @@ -2424,7 +2441,7 @@ return { ["cs"]="sirkasazby", ["de"]="satzbreite", ["en"]="makeupwidth", - ["fr"]="largeurmakeup", + ["fr"]="largeurcomposition", ["it"]="ampiezzamakeup", ["nl"]="zetbreedte", ["pe"]="عرض‌آرایش", @@ -2434,12 +2451,17 @@ return { ["cs"]="okr", ["de"]="mar", ["en"]="mar", - ["fr"]="mar", + ["fr"]="rem", ["it"]="mar", ["nl"]="mar", ["pe"]="حاش", ["ro"]="mar", }, + ["marginblock"]={ + ["en"]="marginblock", + ["fr"]="blocmarginal", + ["nl"]="margeblok", + }, ["margindistance"]={ ["cs"]="vzdalenostmarginalie", ["de"]="marginalafstand", @@ -2454,7 +2476,7 @@ return { ["cs"]="marginalnilinka", ["de"]="marginallinie", ["en"]="marginrule", - ["fr"]="margereglee", + ["fr"]="traitmarge", ["it"]="lineamargine", ["nl"]="kantlijn", ["pe"]="خط‌حاشیه", @@ -2514,7 +2536,7 @@ return { ["cs"]="oznacverzi", ["de"]="beschrifteversion", ["en"]="markversion", - ["fr"]="marquageversion", + ["fr"]="marquerversion", ["it"]="marcaversione", ["nl"]="markeerversie", ["pe"]="نسخه‌نشانه", @@ -2524,7 +2546,7 @@ return { ["cs"]="matematika", ["de"]="mathematik", ["en"]="mathematics", - ["fr"]="mathematique", + ["fr"]="mathematics", ["it"]="matematica", ["nl"]="wiskunde", ["pe"]="ریاضی", @@ -2544,7 +2566,7 @@ return { ["cs"]="maoramovani", ["de"]="maumrise", ["en"]="maframed", - ["fr"]="mframed", + ["fr"]="encadremath", ["it"]="maframed", ["nl"]="wilijnd", ["pe"]="mframed", @@ -2564,7 +2586,7 @@ return { ["cs"]="zrcadlit", ["de"]="spiegeln", ["en"]="mirror", - ["fr"]="reflete", + ["fr"]="refleter", ["it"]="riflessione", ["nl"]="spiegel", ["pe"]="آینه", @@ -2584,7 +2606,7 @@ return { ["cs"]="moveformula", ["de"]="moveformula", ["en"]="moveformula", - ["fr"]="deplaceformule", + ["fr"]="deplacerformule", ["it"]="spostaformula", ["nl"]="verplaatsformule", ["pe"]="انتقال‌فرمول", @@ -2594,7 +2616,7 @@ return { ["cs"]="premistinamrizku", ["de"]="amgitterneuausrichten", ["en"]="moveongrid", - ["fr"]="deplacesurgrille", + ["fr"]="deplacersurgrille", ["it"]="spostaagriglia", ["nl"]="verplaatsopgrid", ["pe"]="انتقال‌به‌توری", @@ -2604,7 +2626,7 @@ return { ["cs"]="movesidefloat", ["de"]="movesidefloat", ["en"]="movesidefloat", - ["fr"]="movesidefloat", + ["fr"]="deplacerflottantcote", ["it"]="movesidefloat", ["nl"]="verplaatszijblok", ["pe"]="انتقال‌کنار‌شناور", @@ -2614,7 +2636,7 @@ return { ["cs"]="navigating", ["de"]="navigating", ["en"]="navigating", - ["fr"]="navigating", + ["fr"]="navigation", ["it"]="navigating", ["nl"]="navigerend", ["pe"]="هدایت", @@ -2634,7 +2656,7 @@ return { ["cs"]="zadnezahlaviaupati", ["de"]="keinekopfundfusszeilen", ["en"]="noheaderandfooterlines", - ["fr"]="sanslignesenteteetpdp", + ["fr"]="sansentêtenipdp", ["it"]="nientelineintestazionepdp", ["nl"]="geenhoofdenvoetregels", ["pe"]="بدون‌خط‌سروته‌برگ", @@ -2644,7 +2666,7 @@ return { ["cs"]="zadneodsazovani", ["de"]="nichteinziehen", ["en"]="noindenting", - ["fr"]="sansalinea", + ["fr"]="sansindentation", ["it"]="nienterientro", ["nl"]="nietinspringen", ["pe"]="بدون‌تورفتگی", @@ -2674,7 +2696,7 @@ return { ["cs"]="zadnedalsibloky", ["de"]="keinebloeckemehr", ["en"]="nomoreblocks", - ["fr"]="pasplusdeblocs", + ["fr"]="sansplusdeblocs", ["it"]="bastablocchi", ["nl"]="geenblokkenmeer", ["pe"]="بدون‌بلوکهای‌بیشتر", @@ -2684,7 +2706,7 @@ return { ["cs"]="zadnedalsisoubory", ["de"]="keinedateienmehr", ["en"]="nomorefiles", - ["fr"]="pasplusdefichiers", + ["fr"]="sansplusdefichiers", ["it"]="bastafile", ["nl"]="geenfilesmeer", ["pe"]="بدون‌فایلهای‌بیشتر", @@ -2694,7 +2716,7 @@ return { ["cs"]="nop", ["de"]="nop", ["en"]="nop", - ["fr"]="nop", + ["fr"]="san", ["it"]="nop", ["nl"]="nop", ["pe"]="منفی", @@ -2724,7 +2746,7 @@ return { ["cs"]="zadnehorniadolniradky", ["de"]="keinzeilenobenundunten", ["en"]="notopandbottomlines", - ["fr"]="sanslignessupetinf", + ["fr"]="sansligneshautetbas", ["it"]="nientelineecimafondo", ["nl"]="geenbovenenonderregels", ["pe"]="بدون‌خط‌بالاوپایین", @@ -2734,7 +2756,7 @@ return { ["cs"]="nokap", ["de"]="nokap", ["en"]="nocap", - ["fr"]="nocap", + ["fr"]="paspetitescaps", ["it"]="nocap", ["nl"]="nokap", ["pe"]="سرپوش‌کوچک‌نه", @@ -2774,7 +2796,7 @@ return { ["cs"]="outeredgedistance", ["de"]="outeredgedistance", ["en"]="outeredgedistance", - ["fr"]="outeredgedistance", + ["fr"]="distancebordexterieur", ["it"]="outeredgedistance", ["nl"]="buitenrandafstand", ["pe"]="فاصله‌لبه‌خارجی", @@ -2784,7 +2806,7 @@ return { ["cs"]="outeredgewidth", ["de"]="outeredgewidth", ["en"]="outeredgewidth", - ["fr"]="outeredgewidth", + ["fr"]="largeurbordexterieur", ["it"]="outeredgewidth", ["nl"]="buitenrandbreedte", ["pe"]="عرض‌لبه‌خارجی", @@ -2794,7 +2816,7 @@ return { ["cs"]="outermargindistance", ["de"]="outermargindistance", ["en"]="outermargindistance", - ["fr"]="outermargindistance", + ["fr"]="distancemargeexterieure", ["it"]="outermargindistance", ["nl"]="buitenmargeafstand", ["pe"]="فاصله‌حاشیه‌خارجی", @@ -2804,7 +2826,7 @@ return { ["cs"]="outermarginwidth", ["de"]="outermarginwidth", ["en"]="outermarginwidth", - ["fr"]="outermarginwidth", + ["fr"]="largeurmargeexterieure", ["it"]="outermarginwidth", ["nl"]="buitenmargebreedte", ["pe"]="عرض‌حاشیه‌خارجی", @@ -2814,7 +2836,7 @@ return { ["cs"]="zhustene", ["de"]="kleinerdurchschuss", ["en"]="packed", - ["fr"]="groupe", + ["fr"]="sansespaceentreitem", ["it"]="impaccato", ["nl"]="opelkaar", ["pe"]="فشرده", @@ -2834,7 +2856,7 @@ return { ["cs"]="pagedepth", ["de"]="pagedepth", ["en"]="pagedepth", - ["fr"]="pagedepth", + ["fr"]="profondeurpage", ["it"]="pagedepth", ["nl"]="paginadiepte", ["pe"]="عمق‌صفحه", @@ -2854,7 +2876,7 @@ return { ["cs"]="pageoffset", ["de"]="pageoffset", ["en"]="pageoffset", - ["fr"]="pageoffset", + ["fr"]="decalagepage", ["it"]="pageoffset", ["nl"]="paginaoffset", ["pe"]="آفست‌صفحه", @@ -2904,7 +2926,7 @@ return { ["cs"]="umistizalozky", ["de"]="platzierebookmarks", ["en"]="placebookmarks", - ["fr"]="placemarquespages", + ["fr"]="placermarquepages", ["it"]="mettisegnalibro", ["nl"]="plaatsbookmarks", ["pe"]="درج‌چوب‌خط", @@ -2914,7 +2936,7 @@ return { ["cs"]="umistikombinovanyseznam", ["de"]="platzierezusammengestellteliste", ["en"]="placecombinedlist", - ["fr"]="placelisteinmbriquee", + ["fr"]="placerlistecombinee", ["it"]="mettielencocombinato", ["nl"]="plaatssamengesteldelijst", ["pe"]="درج‌لیست‌مختلط", @@ -2924,7 +2946,7 @@ return { ["cs"]="placefloat", ["de"]="placefloat", ["en"]="placefloat", - ["fr"]="placeflottant", + ["fr"]="placerflottant", ["it"]="placefloat", ["nl"]="plaatsplaatsblok", ["pe"]="درج‌شناور", @@ -2934,7 +2956,7 @@ return { ["cs"]="umistipoznamkypodcarou", ["de"]="platzierefussnoten", ["en"]="placefootnotes", - ["fr"]="placenotespdp", + ["fr"]="placernotesbdp", ["it"]="mettinotepdp", ["nl"]="plaatsvoetnoten", ["pe"]="درج‌پانوشتها", @@ -2944,7 +2966,7 @@ return { ["cs"]="umistirovnici", ["de"]="platziereformel", ["en"]="placeformula", - ["fr"]="placeformule", + ["fr"]="placerformule", ["it"]="mettiformula", ["nl"]="plaatsformule", ["pe"]="درج‌فرمول", @@ -2954,7 +2976,7 @@ return { ["cs"]="placeheadnumber", ["de"]="placeheadnumber", ["en"]="placeheadnumber", - ["fr"]="placenumerotete", + ["fr"]="placernumerotete", ["it"]="posizionanumerotesta", ["nl"]="plaatskopnummer", ["pe"]="درج‌شماره‌سر", @@ -2964,7 +2986,7 @@ return { ["cs"]="placeheadtext", ["de"]="placeheadtext", ["en"]="placeheadtext", - ["fr"]="placetextetete", + ["fr"]="placertextetete", ["it"]="posizionatestotesta", ["nl"]="plaatskoptekst", ["pe"]="درج‌متن‌سر", @@ -2974,7 +2996,7 @@ return { ["cs"]="umistilegendu", ["de"]="platzierelegende", ["en"]="placelegend", - ["fr"]="placelegende", + ["fr"]="placerlegende", ["it"]="mettilegenda", ["nl"]="plaatslegenda", ["pe"]="درج‌راهنما", @@ -2984,7 +3006,7 @@ return { ["cs"]="umistiseznam", ["de"]="platziereliste", ["en"]="placelist", - ["fr"]="placeliste", + ["fr"]="placerliste", ["it"]="mettielenco", ["nl"]="plaatslijst", ["pe"]="درج‌لیست", @@ -2992,13 +3014,14 @@ return { }, ["placelistofsynonyms"]={ ["en"]="placelistofsynonyms", + ["fr"]="placerlistedesynonymes", ["nl"]="plaatslijstmetsynoniemen", }, ["placelocalfootnotes"]={ ["cs"]="umistilokalnipoznamkypodcarou", ["de"]="platzierelokalefussnoten", ["en"]="placelocalfootnotes", - ["fr"]="placenotespdplocales", + ["fr"]="placernotesbdplocales", ["it"]="mettinotepdplocali", ["nl"]="plaatslokalevoetnoten", ["pe"]="درج‌پانوشتهای‌موضعی", @@ -3008,7 +3031,7 @@ return { ["cs"]="umistiloga", ["de"]="platzierelogo", ["en"]="placelogos", - ["fr"]="placelogos", + ["fr"]="placerlogo", ["it"]="mettiloghi", ["nl"]="plaatsbeeldmerken", ["pe"]="درج‌آرمها", @@ -3018,7 +3041,7 @@ return { ["cs"]="umistinamrizku", ["de"]="amgitterausrichten", ["en"]="placeongrid", - ["fr"]="placesurgrille", + ["fr"]="placersurgrille", ["it"]="mettiingriglia", ["nl"]="plaatsopgrid", ["pe"]="درج‌در‌توری", @@ -3028,7 +3051,7 @@ return { ["cs"]="umistinadsebe", ["de"]="platziereuntereinander", ["en"]="placeontopofeachother", - ["fr"]="placelesunsaudessusdesautres", + ["fr"]="placerlunaudessusdelautre", ["it"]="mettiunosullaltro", ["nl"]="plaatsonderelkaar", ["pe"]="درج‌در‌بالای‌یکدیگر", @@ -3038,7 +3061,7 @@ return { ["cs"]="placepagenumber", ["de"]="placepagenumber", ["en"]="placepagenumber", - ["fr"]="placenumeropage", + ["fr"]="placernumeropage", ["it"]="mettinumeropagina", ["nl"]="plaatspaginanummer", ["pe"]="درج‌شماره‌صفحه", @@ -3048,7 +3071,7 @@ return { ["cs"]="placerawlist", ["de"]="placerawlist", ["en"]="placerawlist", - ["fr"]="placerawlist", + ["fr"]="placerlistebrute", ["it"]="placerawlist", ["nl"]="plaatsruwelijst", ["pe"]="درج‌لیست‌خام", @@ -3058,7 +3081,7 @@ return { ["cs"]="placereferencelist", ["de"]="placereferencelist", ["en"]="placereferencelist", - ["fr"]="placelistereference", + ["fr"]="placerlistereference", ["it"]="placereferencelist", ["nl"]="plaatsreferentielijst", ["pe"]="درج‌لیست‌مرجع", @@ -3068,7 +3091,7 @@ return { ["cs"]="umistirejstrik", ["de"]="platziereregister", ["en"]="placeregister", - ["fr"]="placeregistre", + ["fr"]="placerregistre", ["it"]="mettiregistro", ["nl"]="plaatsregister", ["pe"]="درج‌ثبت", @@ -3078,7 +3101,7 @@ return { ["cs"]="placerule", ["de"]="placerule", ["en"]="placerule", - ["fr"]="placeregle", + ["fr"]="placertrait", ["it"]="mettilinea", ["nl"]="plaatslijn", ["pe"]="درج‌خط", @@ -3088,7 +3111,7 @@ return { ["cs"]="umistivedlesebe", ["de"]="platzierenebeneinander", ["en"]="placesidebyside", - ["fr"]="placecoteacote", + ["fr"]="placercoteacote", ["it"]="mettifiancoafianco", ["nl"]="plaatsnaastelkaar", ["pe"]="درج‌کنار‌به‌کنار", @@ -3098,7 +3121,7 @@ return { ["cs"]="umistipodrovnici", ["de"]="platziereunterformel", ["en"]="placesubformula", - ["fr"]="placesousformule", + ["fr"]="placersousformule", ["it"]="mettisottoformula", ["nl"]="plaatssubformule", ["pe"]="درج‌زیرفرمول", @@ -3108,7 +3131,7 @@ return { ["cs"]="placetextvariable", ["de"]="placetextvariable", ["en"]="placetextvariable", - ["fr"]="placevariabletexte", + ["fr"]="placervariabletexte", ["it"]="mettivariabiletesto", ["nl"]="plaatstekstvariabele", ["pe"]="درج‌متغیرمتن", @@ -3128,7 +3151,7 @@ return { ["cs"]="positiontext", ["de"]="positiontext", ["en"]="positiontext", - ["fr"]="positionnetexte", + ["fr"]="texteposition", ["it"]="posizionatesto", ["nl"]="positioneertekst", ["pe"]="مکان‌متن", @@ -3138,7 +3161,7 @@ return { ["cs"]="vyskatiskpapiru", ["de"]="printpapierhoehe", ["en"]="printpaperheight", - ["fr"]="hauteureditionpapier", + ["fr"]="hauteurpapierimpression", ["it"]="altezzacartastampa", ["nl"]="printpapierhoogte", ["pe"]="چاپ‌ارتفاع‌برگ", @@ -3148,7 +3171,7 @@ return { ["cs"]="sirkatiskpapiru", ["de"]="printpapierbreite", ["en"]="printpaperwidth", - ["fr"]="largeureditionpapier", + ["fr"]="largeurpapierimpression", ["it"]="ampiezzacartastampa", ["nl"]="printpapierbreedte", ["pe"]="چاپ‌عرض‌برگ", @@ -3158,7 +3181,7 @@ return { ["cs"]="zpracujbloky", ["de"]="bearbeitebloecke", ["en"]="processblocks", - ["fr"]="traiteblocs", + ["fr"]="traiterblocs", ["it"]="elaborablocchi", ["nl"]="verwerkblokken", ["pe"]="بلوکهای‌پردازش", @@ -3168,7 +3191,7 @@ return { ["cs"]="zpracujstranu", ["de"]="bearbeiteseite", ["en"]="processpage", - ["fr"]="traitepage", + ["fr"]="traiterpage", ["it"]="elaborapagina", ["nl"]="verwerkpagina", ["pe"]="صفحه‌پردازش", @@ -3248,7 +3271,7 @@ return { ["cs"]="opakovat", ["de"]="wiederholen", ["en"]="redo", - ["fr"]="refait", + ["fr"]="refaire", ["it"]="rifai", ["nl"]="herhaal", ["pe"]="انجام‌دوباره", @@ -3278,7 +3301,7 @@ return { ["cs"]="odkaz", ["de"]="verweis", ["en"]="referral", - ["fr"]="recommandation", + ["fr"]="redirection", ["it"]="referral", ["nl"]="kenmerk", ["pe"]="رجوع", @@ -3288,7 +3311,7 @@ return { ["cs"]="odkaznadatum", ["de"]="verweisdatum", ["en"]="referraldate", - ["fr"]="daterecommandation", + ["fr"]="dateredirection", ["it"]="datareferral", ["nl"]="kenmerkdatum", ["pe"]="تاریخ‌رجوع", @@ -3298,7 +3321,7 @@ return { ["cs"]="odkazujici", ["de"]="referieren", ["en"]="referring", - ["fr"]="faitreference", + ["fr"]="fairereference", ["it"]="referring", ["nl"]="refereer", ["pe"]="مراجعه", @@ -3308,7 +3331,7 @@ return { ["cs"]="oznaceni", ["de"]="bemerkung", ["en"]="remark", - ["fr"]="commentaire", + ["fr"]="remarque", ["it"]="commento", ["nl"]="toelichting", ["pe"]="توجه", @@ -3348,7 +3371,7 @@ return { ["cs"]="resettextcontent", ["de"]="resettextcontent", ["en"]="resettextcontent", - ["fr"]="resettextcontent", + ["fr"]="raztexte", ["it"]="resettextcontent", ["nl"]="resettekstinhoud", ["pe"]="بازنشانی‌متن", @@ -3418,7 +3441,7 @@ return { ["cs"]="otocit", ["de"]="drehen", ["en"]="rotate", - ["fr"]="oriente", + ["fr"]="tourner", ["it"]="ruota", ["nl"]="roteer", ["pe"]="دوران", @@ -3426,13 +3449,14 @@ return { }, ["savebuffer"]={ ["en"]="savebuffer", + ["fr"]="enregistrertampon", ["nl"]="bewaarbuffer", }, ["scale"]={ ["cs"]="meritko", ["de"]="format", ["en"]="scale", - ["fr"]="echelle", + ["fr"]="mettrealechelle", ["it"]="scala", ["nl"]="schaal", ["pe"]="مقیاس", @@ -3452,7 +3476,7 @@ return { ["cs"]="vyberbloky", ["de"]="waehlebloeckeaus", ["en"]="selectblocks", - ["fr"]="selectionneblocs", + ["fr"]="selectionnerblocs", ["it"]="selezionablocchi", ["nl"]="selecteerblokken", ["pe"]="انتخاب‌بلوکها", @@ -3462,7 +3486,7 @@ return { ["cs"]="vyberpapir", ["de"]="waehlepapieraus", ["en"]="selectpaper", - ["fr"]="selectionnepapier", + ["fr"]="selectionnerpapier", ["it"]="selezionacarta", ["nl"]="selecteerpapier", ["pe"]="انتخاب‌برگ", @@ -3472,7 +3496,7 @@ return { ["cs"]="vyberverzi", ["de"]="waehleversionaus", ["en"]="selectversion", - ["fr"]="selectionneversion", + ["fr"]="selectionnerversion", ["it"]="selezionaversione", ["nl"]="selecteerversie", ["pe"]="انتخاب‌نسخه", @@ -3482,7 +3506,7 @@ return { ["cs"]="setnumber", ["de"]="setnumber", ["en"]="setnumber", - ["fr"]="affectenumero", + ["fr"]="reglernumero", ["it"]="setnumber", ["nl"]="setnummer", ["pe"]="تعیین‌شماره", @@ -3492,7 +3516,7 @@ return { ["cs"]="settextcontent", ["de"]="settext", ["en"]="settextcontent", - ["fr"]="settext", + ["fr"]="reglercontenutexte", ["it"]="settext", ["nl"]="steltekstinhoudin", ["pe"]="تعیین‌محتوای‌متن", @@ -3502,7 +3526,7 @@ return { ["cs"]="settextvariable", ["de"]="settextvariable", ["en"]="settextvariable", - ["fr"]="affectevariabletexte", + ["fr"]="reglervariabletexte", ["it"]="setvariabiletesto", ["nl"]="kentekstvariabeletoe", ["pe"]="تعیین‌متغیر‌متن", @@ -3512,7 +3536,7 @@ return { ["cs"]="nastavzarovnani", ["de"]="stelleausrichtungein", ["en"]="setupalign", - ["fr"]="reglealignement", + ["fr"]="configureraligner", ["it"]="impostaallineamento", ["nl"]="steluitlijnenin", ["pe"]="بارگذاری‌تنظیم", @@ -3522,7 +3546,7 @@ return { ["cs"]="setupanswerarea", ["de"]="setupanswerarea", ["en"]="setupanswerarea", - ["fr"]="setupanswerarea", + ["fr"]="configurerzonereponse", ["it"]="setupanswerarea", ["nl"]="stelantwoordgebiedin", ["pe"]="setupanswerarea", @@ -3532,7 +3556,7 @@ return { ["cs"]="nastavusporadani", ["de"]="stelleanordnenein", ["en"]="setuparranging", - ["fr"]="reglearrangement", + ["fr"]="configurerarrangement", ["it"]="impostaparranging", ["nl"]="stelarrangerenin", ["pe"]="بارگذاری‌ترتیب", @@ -3542,7 +3566,7 @@ return { ["cs"]="nastavpozadi", ["de"]="stellehintergrundein", ["en"]="setupbackground", - ["fr"]="reglearriereplan", + ["fr"]="configurerarriereplan", ["it"]="impostasfondo", ["nl"]="stelachtergrondin", ["pe"]="بارگذاری‌پس‌زمینه", @@ -3552,7 +3576,7 @@ return { ["cs"]="nastavpozadi", ["de"]="stellehintergruendeein", ["en"]="setupbackgrounds", - ["fr"]="reglearriereplans", + ["fr"]="configurerarriereplans", ["it"]="impostasfondi", ["nl"]="stelachtergrondenin", ["pe"]="بارگذاری‌پس‌زمینه‌ها", @@ -3562,7 +3586,7 @@ return { ["cs"]="nastavcernelinky", ["de"]="stellerechteckein", ["en"]="setupblackrules", - ["fr"]="reglelignesnoires", + ["fr"]="configurertraitsepais", ["it"]="impostalineenere", ["nl"]="stelblokjesin", ["pe"]="بارگذاری‌خطهای‌سیاه", @@ -3572,7 +3596,7 @@ return { ["cs"]="nastavpreskok", ["de"]="stelleblankoein", ["en"]="setupblank", - ["fr"]="definitvide", + ["fr"]="configurervierge", ["it"]="impostarigovuoto", ["nl"]="stelblankoin", ["pe"]="بارگذاری‌خالی", @@ -3582,7 +3606,7 @@ return { ["cs"]="nastavblok", ["de"]="stelleblockein", ["en"]="setupblock", - ["fr"]="reglebloc", + ["fr"]="configurerbloc", ["it"]="impostablocco", ["nl"]="stelblokin", ["pe"]="بارگذاری‌بلوک", @@ -3592,7 +3616,7 @@ return { ["cs"]="nastavzakladnifont", ["de"]="stellefliesstextein", ["en"]="setupbodyfont", - ["fr"]="reglepolicecorps", + ["fr"]="configurerpolicedecorps", ["it"]="impostafontdeltesto", ["nl"]="stelkorpsin", ["pe"]="بارگذاری‌قلم‌متن", @@ -3602,7 +3626,7 @@ return { ["cs"]="nastavprostredizakladnihofontu", ["de"]="stellefliesstextumgebungein", ["en"]="setupbodyfontenvironment", - ["fr"]="regleenvironnementpolicecorps", + ["fr"]="configurerenvironnementpolicedecorps", ["it"]="impostaambientefontdeltesto", ["nl"]="stelkorpsomgevingin", ["pe"]="بارگذاری‌محیط‌قلم‌متن", @@ -3612,7 +3636,7 @@ return { ["cs"]="nastavspodek", ["de"]="stelleuntenein", ["en"]="setupbottom", - ["fr"]="regleinf", + ["fr"]="configurerbas", ["it"]="impostafondo", ["nl"]="stelonderin", ["pe"]="بارگذاری‌پایین", @@ -3622,7 +3646,7 @@ return { ["cs"]="nastavdolnitexty", ["de"]="stelletextuntenein", ["en"]="setupbottomtexts", - ["fr"]="regletextesinf", + ["fr"]="configurertextesbas", ["it"]="impostatestifondo", ["nl"]="stelondertekstenin", ["pe"]="بارگذاری‌متن‌پایین", @@ -3632,7 +3656,7 @@ return { ["cs"]="nastavbuffer", ["de"]="stellepufferein", ["en"]="setupbuffer", - ["fr"]="reglebuffer", + ["fr"]="configurertampon", ["it"]="impostabuffer", ["nl"]="stelbufferin", ["pe"]="بارگذاری‌بافر", @@ -3642,7 +3666,7 @@ return { ["cs"]="nastavtlacitka", ["de"]="stelleknopfein", ["en"]="setupbuttons", - ["fr"]="regleboutons", + ["fr"]="configurerboutons", ["it"]="impostapulsanti", ["nl"]="stelbuttonsin", ["pe"]="بارگذاری‌دکمه‌ها", @@ -3652,7 +3676,7 @@ return { ["cs"]="nastavkapitalky", ["de"]="stelleversalienein", ["en"]="setupcapitals", - ["fr"]="reglecapitales", + ["fr"]="configurercapitales", ["it"]="impostamaiuscole", ["nl"]="stelkapitalenin", ["pe"]="setupcapitals", @@ -3662,7 +3686,7 @@ return { ["cs"]="nastavpopisek", ["de"]="stellebildunterschriftein", ["en"]="setupcaption", - ["fr"]="regleintitule", + ["fr"]="configurerintitule", ["it"]="impostacaption", ["nl"]="stelblokkopjein", ["pe"]="بارگذاری‌شرح", @@ -3672,7 +3696,7 @@ return { ["cs"]="nastavpopisky", ["de"]="stellebilderunterschriftein", ["en"]="setupcaptions", - ["fr"]="regleintitules", + ["fr"]="configurerintitules", ["it"]="impostacaptions", ["nl"]="stelblokkopjesin", ["pe"]="بارگذاری‌شرحها", @@ -3682,7 +3706,7 @@ return { ["cs"]="nastavorez", ["de"]="stelleausschnittein", ["en"]="setupclipping", - ["fr"]="regleclipping", + ["fr"]="configurerdecoupage", ["it"]="impostaclippling", ["nl"]="stelclipin", ["pe"]="بارگذاری‌چیدن", @@ -3692,7 +3716,7 @@ return { ["cs"]="nastavbarvu", ["de"]="stellefarbeein", ["en"]="setupcolor", - ["fr"]="reglecouleur", + ["fr"]="configurercouleur", ["it"]="impostacolore", ["nl"]="stelkleurin", ["pe"]="بارگذاری‌رنگ", @@ -3702,7 +3726,7 @@ return { ["cs"]="nastavbarvy", ["de"]="stellefarbenein", ["en"]="setupcolors", - ["fr"]="reglecouleurs", + ["fr"]="configurercouleurs", ["it"]="impostacolori", ["nl"]="stelkleurenin", ["pe"]="بارگذاری‌رنگها", @@ -3712,7 +3736,7 @@ return { ["cs"]="nastavsloupce", ["de"]="stellespaltenein", ["en"]="setupcolumns", - ["fr"]="reglecolonnes", + ["fr"]="configurercolonnes", ["it"]="impostacolonne", ["nl"]="stelkolommenin", ["pe"]="بارگذاری‌ستونها", @@ -3722,7 +3746,7 @@ return { ["cs"]="setupcolumnset", ["de"]="setupcolumnset", ["en"]="setupcolumnset", - ["fr"]="reglejeucolonne", + ["fr"]="configurerjeucolonnes", ["it"]="impostagruppocolonne", ["nl"]="stelkolomgroepin", ["pe"]="بارگذاری‌مجموعه‌ستون", @@ -3732,7 +3756,7 @@ return { ["cs"]="setupcolumnsetlines", ["de"]="setupcolumnsetlines", ["en"]="setupcolumnsetlines", - ["fr"]="setupcolumnsetlines", + ["fr"]="configurerlignesjeucolonnes", ["it"]="setupcolumnsetlines", ["nl"]="stelkolomgroepregelsin", ["pe"]="بارگذاری‌خطهای‌مجموعه‌ستون", @@ -3742,7 +3766,7 @@ return { ["cs"]="setupcolumnsetstart", ["de"]="setupcolumnsetstart", ["en"]="setupcolumnsetstart", - ["fr"]="setupcolumnsetstart", + ["fr"]="configurerfinjeucolonnes", ["it"]="setupcolumnsetstart", ["nl"]="stelkolomgroepstartin", ["pe"]="بارگذاری‌شروع‌مجموعه‌ستون", @@ -3752,7 +3776,7 @@ return { ["cs"]="nastavspojeni", ["de"]="stellekombinationein", ["en"]="setupcombinations", - ["fr"]="reglecombinaisons", + ["fr"]="configurercombinaisons", ["it"]="impostacombinazioni", ["nl"]="stelcombinatiesin", ["pe"]="بارگذاری‌ترکیب‌ها", @@ -3762,7 +3786,7 @@ return { ["cs"]="nastavkombinovanyseznam", ["de"]="stellezusammengestelltelisteein", ["en"]="setupcombinedlist", - ["fr"]="reglelisteimbriquee", + ["fr"]="configurerlistecombinee", ["it"]="impostaelencocombinato", ["nl"]="stelsamengesteldelijstin", ["pe"]="بارگذاری‌لیست‌ترکیبی", @@ -3772,45 +3796,47 @@ return { ["cs"]="nastavkomentar", ["de"]="stellekommentarein", ["en"]="setupcomment", - ["fr"]="reglecommentaire", + ["fr"]="configurercommentaire", ["it"]="impostacommento", ["nl"]="stelcommentaarin", ["pe"]="بارگذاری‌توضیح", ["ro"]="seteazacomentariu", }, + ["setupdescription"]={ + ["en"]="setupdescription", + ["fr"]="configurerdescription", + ["nl"]="steldoordefinierenin", + }, ["setupdescriptions"]={ ["cs"]="nastavpopisy", ["de"]="definierebeschreibungen", ["en"]="setupdescriptions", - ["fr"]="regledescriptions", + ["fr"]="configurerdescriptions", ["it"]="impostadescrizioni", ["nl"]="steldoordefinierenin", ["pe"]="بارگذاری‌شرح", ["ro"]="seteazadescriere", }, - ["setupdescription"]={ - ["en"]="setupdescription", - ["nl"]="steldoordefinierenin", + ["setupenumeration"]={ + ["en"]="setupenumeration", + ["fr"]="configurerénumération", + ["nl"]="steldoornummerenin", }, ["setupenumerations"]={ ["cs"]="nastavvycty", ["de"]="stellebeschreibungein", ["en"]="setupenumerations", - ["fr"]="regleenumerations", + ["fr"]="configurerénumérations", ["it"]="impostaenumerazioni", ["nl"]="steldoornummerenin", ["pe"]="بارگذاری‌شماره‌گذاریها", ["ro"]="seteazaenumerare", }, - ["setupenumeration"]={ - ["en"]="setupenumeration", - ["nl"]="steldoornummerenin", - }, ["setupexternalfigures"]={ ["cs"]="nastavexterniobrazy", ["de"]="stelleexterneabbildungenein", ["en"]="setupexternalfigures", - ["fr"]="reglefiguresexternes", + ["fr"]="configurerfiguresexterne", ["it"]="impostafigureesterne", ["nl"]="stelexternefigurenin", ["pe"]="بارگذاری‌شکلهای‌خارجی", @@ -3820,7 +3846,7 @@ return { ["cs"]="nastavpole", ["de"]="stellefeldein", ["en"]="setupfield", - ["fr"]="reglechamp", + ["fr"]="configurerchamp", ["it"]="impostacampo", ["nl"]="stelveldin", ["pe"]="بارگذاری‌میدان", @@ -3830,7 +3856,7 @@ return { ["cs"]="nastavvsechnapole", ["de"]="stellefelderin", ["en"]="setupfields", - ["fr"]="reglechamps", + ["fr"]="configurerchamps", ["it"]="impostacampi", ["nl"]="stelveldenin", ["pe"]="بارگذاری‌میدانها", @@ -3840,7 +3866,7 @@ return { ["cs"]="nastavvyplnoveradky", ["de"]="stellegefuelltezeileein", ["en"]="setupfillinlines", - ["fr"]="regleremplitligne", + ["fr"]="configurerlignesarenseigner", ["it"]="impostarigheriempimento", ["nl"]="stelinvulregelsin", ["pe"]="بارگذاری‌پرکردن‌خطها", @@ -3850,7 +3876,7 @@ return { ["cs"]="nastavvyplnovelinky", ["de"]="stellegefuelltesrechteckein", ["en"]="setupfillinrules", - ["fr"]="regleremplitlignesreglees", + ["fr"]="configurertraitsarenseigner", ["it"]="impostalineeriempimento", ["nl"]="stelinvullijnenin", ["pe"]="بارگذاری‌درج‌درخطها", @@ -3860,7 +3886,7 @@ return { ["cs"]="nastavplvouciobjekt", ["de"]="stellegleitobjektein", ["en"]="setupfloat", - ["fr"]="regleflottant", + ["fr"]="configurerflottant", ["it"]="impostaoggettomobile", ["nl"]="stelplaatsblokin", ["pe"]="بارگذاری‌شناور", @@ -3870,7 +3896,7 @@ return { ["cs"]="nastavplvouciobjekty", ["de"]="stellegleitobjekteein", ["en"]="setupfloats", - ["fr"]="regleflottants", + ["fr"]="configurerflottants", ["it"]="impostaoggettimobili", ["nl"]="stelplaatsblokkenin", ["pe"]="بارگذاری‌شناورها", @@ -3880,7 +3906,7 @@ return { ["cs"]="nastavdeleniplvoucichobjektu", ["de"]="stelleplatziegeteiltegleitobjekt", ["en"]="setupfloatsplitting", - ["fr"]="regleseparationflottant", + ["fr"]="configurerpartageflottants", ["it"]="impostaspezzamentooggettomobile", ["nl"]="stelplaatsbloksplitsenin", ["pe"]="بارگذاری‌شکافتن‌شناورها", @@ -3890,7 +3916,7 @@ return { ["cs"]="nastavupati", ["de"]="stellefusszeileein", ["en"]="setupfooter", - ["fr"]="reglepdp", + ["fr"]="configurerpdp", ["it"]="impostapdp", ["nl"]="stelvoetin", ["pe"]="بارگذاری‌ته‌برگ", @@ -3900,7 +3926,7 @@ return { ["cs"]="nastavtextyupati", ["de"]="stellefusszeilentextein", ["en"]="setupfootertexts", - ["fr"]="regletextespdp", + ["fr"]="configurertextespdp", ["it"]="impostatestipdp", ["nl"]="stelvoettekstenin", ["pe"]="بارگذاری‌متن‌پانوشت", @@ -3910,7 +3936,7 @@ return { ["cs"]="nastavdefinicipoznamekpodcarou", ["de"]="stellefussnotendefinitionein", ["en"]="setupfootnotedefinition", - ["fr"]="definitnotepdp", + ["fr"]="configurerdefinitionnotebdp", ["it"]="impostadefinizionenotepdp", ["nl"]="stelvoetnootdefinitiein", ["pe"]="بارگذاری‌تعریف‌پانوشت", @@ -3920,7 +3946,7 @@ return { ["cs"]="nastavpoznamkypodcarou", ["de"]="stellefussnotenein", ["en"]="setupfootnotes", - ["fr"]="reglenotepdp", + ["fr"]="configurernotesbdp", ["it"]="impostanotepdp", ["nl"]="stelvoetnotenin", ["pe"]="بارگذاری‌پانوشتها", @@ -3930,55 +3956,57 @@ return { ["cs"]="setupforms", ["de"]="setupforms", ["en"]="setupforms", - ["fr"]="regleformulaires", + ["fr"]="configurerformulaires", ["it"]="impostaforms", ["nl"]="stelformulierenin", ["pe"]="بارگذاری‌طرح", ["ro"]="seteazaformulare", }, + ["setupformula"]={ + ["en"]="setupformula", + ["fr"]="configurerformule", + ["nl"]="stelformulein", + }, ["setupformulas"]={ ["cs"]="nastavrovnice", ["de"]="stelleformelnein", ["en"]="setupformulae", - ["fr"]="regleformules", + ["fr"]="configurerformules", ["it"]="impostaformule", ["nl"]="stelformulesin", ["pe"]="بارگذاری‌فرمولها", ["ro"]="seteazaformule", }, - ["setupformula"]={ - ["en"]="setupformula", - ["nl"]="stelformulein", - }, ["setupframed"]={ ["cs"]="nastavoramovani", ["de"]="stelleumrahmtein", ["en"]="setupframed", - ["fr"]="regleencadre", + ["fr"]="configurerencadre", ["it"]="impostaincorniciato", ["nl"]="stelomlijndin", ["pe"]="بارگذاری‌قالبی", ["ro"]="seteazainconjurat", }, + ["setupframedtext"]={ + ["en"]="setupframedtext", + ["fr"]="configurertexteencadre", + ["nl"]="stelkadertekstin", + }, ["setupframedtexts"]={ ["cs"]="nastavoramovanetexty", ["de"]="stelleumrahmtetexteein", ["en"]="setupframedtexts", - ["fr"]="setupframedtexts", + ["fr"]="configurertextesencadres", ["it"]="impostatestiincorniciati", ["nl"]="stelkadertekstenin", ["pe"]="بارگذاری‌متن‌قالبی", ["ro"]="definestetexteinconjurate", }, - ["setupframedtext"]={ - ["en"]="setupframedtext", - ["nl"]="stelkadertekstin", - }, ["setuphead"]={ ["cs"]="nastavnadpis", ["de"]="stelleueberschriftein", ["en"]="setuphead", - ["fr"]="regletete", + ["fr"]="configurertête", ["it"]="impostatesta", ["nl"]="stelkopin", ["pe"]="بارگذاری‌سر", @@ -3988,7 +4016,7 @@ return { ["cs"]="nastavzahlavi", ["de"]="stellekopfzeileein", ["en"]="setupheader", - ["fr"]="regleentete", + ["fr"]="configurerentête", ["it"]="impostainstestazione", ["nl"]="stelhoofdin", ["pe"]="بارگذاری‌سربرگ", @@ -3998,7 +4026,7 @@ return { ["cs"]="nastavtextyzahlavi", ["de"]="stellekopfzeilentextein", ["en"]="setupheadertexts", - ["fr"]="regletextesentete", + ["fr"]="configurertextesentête", ["it"]="impostatestiintestazioni", ["nl"]="stelhoofdtekstenin", ["pe"]="بارگذاری‌متن‌سربرگ", @@ -4008,7 +4036,7 @@ return { ["cs"]="nastavcislonadpisu", ["de"]="stellekopfzahlein", ["en"]="setupheadnumber", - ["fr"]="reglenumerotete", + ["fr"]="configurernumerotête", ["it"]="impostanumerotesta", ["nl"]="stelkopnummerin", ["pe"]="بارگذاری‌شماره‌سر", @@ -4018,7 +4046,7 @@ return { ["cs"]="nastavnadpisy", ["de"]="stelleueberschriftenein", ["en"]="setupheads", - ["fr"]="regletetes", + ["fr"]="configurertêtes", ["it"]="impostateste", ["nl"]="stelkoppenin", ["pe"]="بارگذاری‌سرها", @@ -4028,7 +4056,7 @@ return { ["cs"]="nastavtexthlavicky", ["de"]="stelleueberschrifttextein", ["en"]="setupheadtext", - ["fr"]="regletextetete", + ["fr"]="configurertextêtete", ["it"]="impostatestointestazioni", ["nl"]="stelkoptekstin", ["pe"]="بارگذاری‌متن‌سر", @@ -4038,7 +4066,7 @@ return { ["cs"]="nastavdelitko", ["de"]="stellebindestrichein", ["en"]="setuphyphenmark", - ["fr"]="reglemarquagehyphenation", + ["fr"]="configurermarquecesure", ["it"]="impostasegnosillabazione", ["nl"]="stelkoppeltekenin", ["pe"]="بارگذاری‌نشانه‌شکستن", @@ -4046,13 +4074,14 @@ return { }, ["setupindentedtext"]={ ["en"]="setupindentedtext", + ["fr"]="configurertexteindente", ["nl"]="stelingesprongentextin", }, ["setupindenting"]={ ["cs"]="nastavodsazovani", ["de"]="stelleeinziehenein", ["en"]="setupindenting", - ["fr"]="reglecomposeenalinea", + ["fr"]="configurerindentation", ["it"]="impostarientro", ["nl"]="stelinspringenin", ["pe"]="بارگذاری‌تورفتگی", @@ -4062,7 +4091,7 @@ return { ["cs"]="nastavmarginalie", ["de"]="stelleinmarginalieein", ["en"]="setupinmargin", - ["fr"]="regledansmarge", + ["fr"]="configurerdansmarge", ["it"]="impostainmargine", ["nl"]="stelinmargein", ["pe"]="بارگذاری‌درون‌حاشیه", @@ -4072,7 +4101,7 @@ return { ["cs"]="nastavinterakci", ["de"]="stelleinteraktionein", ["en"]="setupinteraction", - ["fr"]="regleinteraction", + ["fr"]="configurerinteraction", ["it"]="impostainterazione", ["nl"]="stelinteractiein", ["pe"]="بارگذاری‌پانل", @@ -4082,7 +4111,7 @@ return { ["cs"]="nastavinterakcnilistu", ["de"]="stelleinteraktionsbalkenein", ["en"]="setupinteractionbar", - ["fr"]="reglebarreinteraction", + ["fr"]="configurerbarreinteraction", ["it"]="impostabarrainterazione", ["nl"]="stelinteractiebalkin", ["pe"]="بارگذاری‌میله‌پانل", @@ -4092,7 +4121,7 @@ return { ["cs"]="nastavinterakcnimenu", ["de"]="stelleinteraktionsmenueein", ["en"]="setupinteractionmenu", - ["fr"]="reglemenuinteraction", + ["fr"]="configurermenuinteraction", ["it"]="impostamenuinterazione", ["nl"]="stelinteractiemenuin", ["pe"]="بارگذاری‌منوی‌پانل", @@ -4102,7 +4131,7 @@ return { ["cs"]="nastavinterakcniobrazovku", ["de"]="stelleinteraktionsbildschirmein", ["en"]="setupinteractionscreen", - ["fr"]="regleecraninteraction", + ["fr"]="configurerecraninteraction", ["it"]="impostaschermointerazione", ["nl"]="stelinteractieschermin", ["pe"]="بارگذاری‌پرده‌پانل", @@ -4112,7 +4141,7 @@ return { ["cs"]="nastavmeziradkovoumezeru", ["de"]="stellezeilenabstandein", ["en"]="setupinterlinespace", - ["fr"]="regleespacementinterligne", + ["fr"]="configurerespaceinterligne", ["it"]="impostainterlinea", ["nl"]="stelinterliniein", ["pe"]="بارگذاری‌فاصله‌بین‌خط", @@ -4122,7 +4151,7 @@ return { ["cs"]="setupitemgroup", ["de"]="setupitemgroup", ["en"]="setupitemgroup", - ["fr"]="setupitemgroup", + ["fr"]="configurergroupedéléments", ["it"]="setupitemgroup", ["nl"]="stelitemgroepin", ["pe"]="بارگذاری‌گروه‌آیتم", @@ -4132,7 +4161,7 @@ return { ["cs"]="nastavvycty", ["de"]="stelleaufzaehlungenein", ["en"]="setupitemizations", - ["fr"]="reglegroupeselements", + ["fr"]="configurergroupesdéléments", ["it"]="impostaelencazioni", ["nl"]="stelopsommingenin", ["pe"]="بارگذاری‌گروههای‌آیتم", @@ -4142,7 +4171,7 @@ return { ["cs"]="nastavpolozky", ["de"]="stellepostenein", ["en"]="setupitems", - ["fr"]="regleelements", + ["fr"]="configureréléments", ["it"]="impostaelementi", ["nl"]="stelitemsin", ["pe"]="بارگذاری‌آیتمها", @@ -4152,7 +4181,7 @@ return { ["cs"]="nastavtextpopisku", ["de"]="stellelabeltextein", ["en"]="setuplabeltext", - ["fr"]="reglelabeltexte", + ["fr"]="configureretiquettetexte", ["it"]="impostatestoetichette", ["nl"]="stellabeltekstin", ["pe"]="باگذاری‌متن‌برچسب", @@ -4162,7 +4191,7 @@ return { ["cs"]="nastavjazyk", ["de"]="stellespracheein", ["en"]="setuplanguage", - ["fr"]="reglelangue", + ["fr"]="configurerlangue", ["it"]="impostalingua", ["nl"]="steltaalin", ["pe"]="بارگذاری‌زبان", @@ -4172,7 +4201,7 @@ return { ["cs"]="nastavvzhled", ["de"]="stellelayoutein", ["en"]="setuplayout", - ["fr"]="regledisposition", + ["fr"]="configurermiseenpage", ["it"]="impostalayout", ["nl"]="stellayoutin", ["pe"]="بارگذاری‌طرح‌بندی", @@ -4182,7 +4211,7 @@ return { ["cs"]="nastavlegendu", ["de"]="stellelegendeein", ["en"]="setuplegend", - ["fr"]="reglelegende", + ["fr"]="configurerlegende", ["it"]="impostalegenda", ["nl"]="stellegendain", ["pe"]="بارگذاری‌راهنما", @@ -4192,7 +4221,7 @@ return { ["cs"]="nastavcislovaniradku", ["de"]="stellezeilennumerierungein", ["en"]="setuplinenumbering", - ["fr"]="reglenumerotationligne", + ["fr"]="configurernumérotationligne", ["it"]="impostanumerazionerighe", ["nl"]="stelregelnummerenin", ["pe"]="بارگذاری‌شماره‌‌گذاری‌خط", @@ -4202,7 +4231,7 @@ return { ["cs"]="nastavradky", ["de"]="stellezeilenein", ["en"]="setuplines", - ["fr"]="reglelignes", + ["fr"]="configurerlignes", ["it"]="impostarighe", ["nl"]="stelregelsin", ["pe"]="بارگذاری‌خطها", @@ -4212,7 +4241,7 @@ return { ["cs"]="nastavsirkucary", ["de"]="stellelinienbreiteein", ["en"]="setuplinewidth", - ["fr"]="regleepaisseurligne", + ["fr"]="configurerepaisseurtrait", ["it"]="impostaampiezzariga", ["nl"]="stellijndiktein", ["pe"]="بارگذاری‌عرض‌خط", @@ -4222,7 +4251,7 @@ return { ["cs"]="nastavseznam", ["de"]="stellelisteein", ["en"]="setuplist", - ["fr"]="regleliste", + ["fr"]="configurerliste", ["it"]="impostaelenco", ["nl"]="stellijstin", ["pe"]="بارگذاری‌لیست", @@ -4232,35 +4261,37 @@ return { ["cs"]="nastavupravu", ["de"]="stelleumbruchein", ["en"]="setupmakeup", - ["fr"]="reglemakeup", + ["fr"]="configurercomposition", ["it"]="impostamakeup", ["nl"]="stelopmaakin", ["pe"]="بارگذاری‌آرایش", ["ro"]="seteazamakeup", }, + ["setupmarginblock"]={ + ["en"]="setupmarginblock", + ["fr"]="configurerblocmarginal", + ["nl"]="stelmargeblokkenin", + }, ["setupmarginblocks"]={ ["cs"]="nastavmarginalniblok", ["de"]="stellemarginalblockein", ["en"]="setupmarginblocks", - ["fr"]="regleblocmarge", + ["fr"]="configurerblocmarge", ["it"]="impostablocchimargine", ["nl"]="stelmargeblokkenin", ["pe"]="بارگذاری‌بلوکهای‌حاشیه", ["ro"]="seteazablocurimarginale", }, - ["setupmarginblock"]={ - ["en"]="setupmarginblock", - ["nl"]="stelmargeblokkenin", - }, ["setupmargindata"]={ ["en"]="setupmargindata", + ["fr"]="configurerdonneesmarginales", ["nl"]="stelinmargein", }, ["setupmarginrules"]={ ["cs"]="nastavmarginalnilinky", ["de"]="stellemarginallinieein", ["en"]="setupmarginrules", - ["fr"]="reglemargereglee", + ["fr"]="configurertraitsmarge", ["it"]="impostalineemargine", ["nl"]="stelkantlijnin", ["pe"]="بارگذاری‌خطهای‌حاشیه", @@ -4270,7 +4301,7 @@ return { ["cs"]="nastavznaceni", ["de"]="stellebeschriftungein", ["en"]="setupmarking", - ["fr"]="reglemarquage", + ["fr"]="configurermarquage", ["it"]="impostamarcatura", ["nl"]="stelmarkeringin", ["pe"]="بارگذاری‌نشانه‌گذاری", @@ -4280,7 +4311,7 @@ return { ["cs"]="setupmathalignment", ["de"]="setupmathalignment", ["en"]="setupmathalignment", - ["fr"]="setupmathalignment", + ["fr"]="configureralignementmath", ["it"]="setupmathalignment", ["nl"]="stelwiskundeuitlijnenin", ["pe"]="بارگذاری‌تنظیم‌ریاضی", @@ -4290,7 +4321,7 @@ return { ["cs"]="nastavzuzeni", ["de"]="stelleengerein", ["en"]="setupnarrower", - ["fr"]="reglecompoetroite", + ["fr"]="configurerplusetroit", ["it"]="impostapiustretto", ["nl"]="stelsmallerin", ["pe"]="بارگذاری‌باریکتر", @@ -4300,7 +4331,7 @@ return { ["cs"]="setupnumber", ["de"]="setupnumber", ["en"]="setupnumber", - ["fr"]="reglenumero", + ["fr"]="configurernumero", ["it"]="impostanumerazione", ["nl"]="stelnummerin", ["pe"]="بارگذاری‌شماره", @@ -4310,7 +4341,7 @@ return { ["cs"]="nastavcislovani", ["de"]="stellenummerierungein", ["en"]="setupnumbering", - ["fr"]="reglenumerotation", + ["fr"]="configurernumérotation", ["it"]="impostanumerazione", ["nl"]="stelnummerenin", ["pe"]="بارگذاری‌شماره‌گذاری", @@ -4320,7 +4351,7 @@ return { ["cs"]="nastavumisteniprotejsku", ["de"]="stellegegenueberplatzierenein", ["en"]="setupoppositeplacing", - ["fr"]="regleplacementopposition", + ["fr"]="configurerplacementopposition", ["it"]="impostaposizionamentoopposti", ["nl"]="stelnaastplaatsenin", ["pe"]="بارگذاری‌درج‌مخالف", @@ -4330,7 +4361,7 @@ return { ["cs"]="nastavvystup", ["de"]="stelleausgabeein", ["en"]="setupoutput", - ["fr"]="reglesortie", + ["fr"]="configurersortie", ["it"]="impostaoutput", ["nl"]="steluitvoerin", ["pe"]="بارگذاری‌خروجی", @@ -4340,7 +4371,7 @@ return { ["cs"]="nastavkomentarstrany", ["de"]="stelleseitenkommentarein", ["en"]="setuppagecomment", - ["fr"]="reglecommentairepage", + ["fr"]="configurercommentairepage", ["it"]="impostacommentopagina", ["nl"]="stelpaginacommentaarin", ["pe"]="بارگذاری‌توضیح‌صفحه", @@ -4350,7 +4381,7 @@ return { ["cs"]="nastavcislostrany", ["de"]="stelleseitennummerein", ["en"]="setuppagenumber", - ["fr"]="reglenumeropage", + ["fr"]="configurernumeropage", ["it"]="impostanumeropagina", ["nl"]="stelpaginanummerin", ["pe"]="بارگذاری‌شماره‌صفحه", @@ -4360,7 +4391,7 @@ return { ["cs"]="nastavcislovanistran", ["de"]="stelleseitennummeriernungein", ["en"]="setuppagenumbering", - ["fr"]="reglenumerotationpage", + ["fr"]="configurernumérotationpage", ["it"]="impostanumerazionepagina", ["nl"]="stelpaginanummeringin", ["pe"]="بارگذاری‌شماره‌گذاری‌صفحه", @@ -4370,7 +4401,7 @@ return { ["cs"]="nastavprechodstrany", ["de"]="stelleseitenuebergangein", ["en"]="setuppagetransitions", - ["fr"]="regletransitionspage", + ["fr"]="configurertransitionpage", ["it"]="impostatransizionepagina", ["nl"]="stelpaginaovergangenin", ["pe"]="بارگذاری‌گذارصفحه", @@ -4380,7 +4411,7 @@ return { ["cs"]="nastavpaletu", ["de"]="stellepaletteein", ["en"]="setuppalet", - ["fr"]="reglepalette", + ["fr"]="configurerpalette", ["it"]="impostatavolozza", ["nl"]="stelpaletin", ["pe"]="بارگذاری‌لوح", @@ -4390,7 +4421,7 @@ return { ["cs"]="setuppaper", ["de"]="setuppaper", ["en"]="setuppaper", - ["fr"]="reglepapier", + ["fr"]="configurerpapier", ["it"]="setuppaper", ["nl"]="stelpapierin", ["pe"]="بارگذاری‌برگ", @@ -4400,7 +4431,7 @@ return { ["cs"]="nastavvelikostpapiru", ["de"]="stellepapierformatein", ["en"]="setuppapersize", - ["fr"]="regletaillepapier", + ["fr"]="configurertaillepapier", ["it"]="impostadimensionicarta", ["nl"]="stelpapierformaatin", ["pe"]="بارگذاری‌اندازه‌برگ", @@ -4410,7 +4441,7 @@ return { ["cs"]="nastavcislovaniodstavcu", ["de"]="stelleabsatznummerierungein", ["en"]="setupparagraphnumbering", - ["fr"]="reglenumerotationparagraphe", + ["fr"]="configurernumérotationparagraphe", ["it"]="impostanumerazionecapoversi", ["nl"]="stelparagraafnummerenin", ["pe"]="بارگذاری‌شماره‌گذاری‌پاراگراف", @@ -4420,7 +4451,7 @@ return { ["cs"]="nastavodstavce", ["de"]="stelleabsaetzeein", ["en"]="setupparagraphs", - ["fr"]="regleparagraphes", + ["fr"]="configurerparagraphe", ["it"]="impostacapoversi", ["nl"]="stelalineasin", ["pe"]="بارگذاری‌پاراگرافها", @@ -4430,7 +4461,7 @@ return { ["cs"]="setupplacement", ["de"]="setupplacement", ["en"]="setupplacement", - ["fr"]="setupplacement", + ["fr"]="configurerplacement", ["it"]="setupplacement", ["nl"]="stelplaatsin", ["pe"]="بارگذاری‌جانشانی", @@ -4440,7 +4471,7 @@ return { ["cs"]="nastavumistovani", ["de"]="stellepositionierenein", ["en"]="setuppositioning", - ["fr"]="reglepositionnement", + ["fr"]="configurerpositionnement", ["it"]="impostaposizionamento", ["nl"]="stelpositionerenin", ["pe"]="بارگذاری‌مکان‌گذاری", @@ -4450,7 +4481,7 @@ return { ["cs"]="nastavprofily", ["de"]="stelleprofilein", ["en"]="setupprofiles", - ["fr"]="regleprofils", + ["fr"]="configurerprofils", ["it"]="impostaprofili", ["nl"]="stelprofielenin", ["pe"]="بارگذاری‌پروفایلها", @@ -4460,7 +4491,7 @@ return { ["cs"]="nastavprogramy", ["de"]="stelleprogrammein", ["en"]="setupprograms", - ["fr"]="regleprogrammes", + ["fr"]="configurerprogrammes", ["it"]="impostaprogrammi", ["nl"]="stelprogrammasin", ["pe"]="بارگذاری‌برنامه‌ها", @@ -4470,7 +4501,7 @@ return { ["cs"]="nastavpublikace", ["de"]="stellepublikationein", ["en"]="setuppublications", - ["fr"]="reglepublications", + ["fr"]="configurerpublications", ["it"]="impostapubblicazioni", ["nl"]="stelpublicatiesin", ["pe"]="بارگذاری‌نشرها", @@ -4480,7 +4511,7 @@ return { ["cs"]="nastavcitaci", ["de"]="stellezitierenein", ["en"]="setupquote", - ["fr"]="demarreciter", + ["fr"]="configurerciter", ["it"]="impostamenzione", ["nl"]="stelciterenin", ["pe"]="بارگذاری‌نقل", @@ -4490,7 +4521,7 @@ return { ["cs"]="nastavseznamodkazu", ["de"]="stellereferenzlisteein", ["en"]="setupreferencelist", - ["fr"]="reglelistereference", + ["fr"]="configurerlistereference", ["it"]="impostalistariferimenti", ["nl"]="stelreferentielijstin", ["pe"]="بارگذاری‌لیست‌مرجع", @@ -4500,7 +4531,7 @@ return { ["cs"]="nastavodkazovani", ["de"]="stellereferenzierenein", ["en"]="setupreferencing", - ["fr"]="reglereferencage", + ["fr"]="configurerreferencement", ["it"]="impostariferimento", ["nl"]="stelrefererenin", ["pe"]="بارگذاری‌ارجاع", @@ -4510,7 +4541,7 @@ return { ["cs"]="nastavrejstrik", ["de"]="stelleregisterein", ["en"]="setupregister", - ["fr"]="regleregistre", + ["fr"]="configurerregistre", ["it"]="impostaregistro", ["nl"]="stelregisterin", ["pe"]="بارگذاری‌ثبت", @@ -4520,7 +4551,7 @@ return { ["cs"]="nastavotoceni", ["de"]="stelledrehenein", ["en"]="setuprotate", - ["fr"]="regleoriente", + ["fr"]="configurerrotation", ["it"]="impostarotazione", ["nl"]="stelroterenin", ["pe"]="بارگذاری‌دوران", @@ -4530,7 +4561,7 @@ return { ["cs"]="setuprule", ["de"]="setuprule", ["en"]="setuprule", - ["fr"]="regleregle", + ["fr"]="configurertrait", ["it"]="impostalinea", ["nl"]="stellijnin", ["pe"]="بارگذاری‌خط", @@ -4540,7 +4571,7 @@ return { ["cs"]="nastavrastr", ["de"]="stellerasterein", ["en"]="setupscreens", - ["fr"]="regleecrans", + ["fr"]="configurerecran", ["it"]="impostaschermi", ["nl"]="stelrastersin", ["pe"]="بارگذاری‌پرده‌ها", @@ -4550,7 +4581,7 @@ return { ["cs"]="nastavsekci", ["de"]="stelleabschnittein", ["en"]="setupsection", - ["fr"]="reglesection", + ["fr"]="configurersection", ["it"]="impostasezione", ["nl"]="stelsectiein", ["pe"]="بارگذاری‌بخش", @@ -4560,7 +4591,7 @@ return { ["cs"]="nastavbloksekce", ["de"]="stelleabschnittsblockein", ["en"]="setupsectionblock", - ["fr"]="regleblocsection", + ["fr"]="configurerblocsection", ["it"]="impostabloccosezione", ["nl"]="stelsectieblokin", ["pe"]="بارگذاری‌بلوک‌بخش", @@ -4570,7 +4601,7 @@ return { ["cs"]="nastavtrideni", ["de"]="stellesortierenein", ["en"]="setupsorting", - ["fr"]="regletri", + ["fr"]="configurertri", ["it"]="impostaordinamento", ["nl"]="stelsorterenin", ["pe"]="بارگذاری‌ترتیب", @@ -4580,7 +4611,7 @@ return { ["cs"]="nastavradkovani", ["de"]="stellespatiumein", ["en"]="setupspacing", - ["fr"]="regleespacement", + ["fr"]="configurerespacement", ["it"]="impostaspaziatura", ["nl"]="stelspatieringin", ["pe"]="بارگذاری‌فضا‌گذاری", @@ -4590,7 +4621,7 @@ return { ["cs"]="setupstartstop", ["de"]="setupstartstop", ["en"]="setupstartstop", - ["fr"]="regledemarrestoppe", + ["fr"]="configurerdébutfin", ["it"]="impostainiziatermina", ["nl"]="stelstartstopin", ["pe"]="بارگذاری‌شروع‌پایان", @@ -4600,7 +4631,7 @@ return { ["cs"]="setupstrut", ["de"]="setupstrut", ["en"]="setupstrut", - ["fr"]="reglestrut", + ["fr"]="configurerentretoise", ["it"]="impostastrut", ["nl"]="stelstrutin", ["pe"]="بارگذاری‌بست", @@ -4610,7 +4641,7 @@ return { ["cs"]="nastavpodcislostrany", ["de"]="stelleunterseitennummerein", ["en"]="setupsubpagenumber", - ["fr"]="reglesousnumeropage", + ["fr"]="configurernumerosouspage", ["it"]="impostanumerosottopagina", ["nl"]="stelsubpaginanummerin", ["pe"]="بارگذاری‌شماره‌زیرصفحه", @@ -4620,7 +4651,7 @@ return { ["cs"]="nastavsadusymbolu", ["de"]="stellesymbolsetein", ["en"]="setupsymbolset", - ["fr"]="reglejeusymboles", + ["fr"]="configurerjeusymboles", ["it"]="impostasetsimboli", ["nl"]="stelsymboolsetin", ["pe"]="بارگذاری‌مجموعه‌نماد", @@ -4630,7 +4661,7 @@ return { ["cs"]="nastavsynchronizaci", ["de"]="stellesynchronisationein", ["en"]="setupsynchronization", - ["fr"]="reglesynchronisation", + ["fr"]="configurersynchronisation", ["it"]="impostasincronizzazione", ["nl"]="stelsynchronisatiein", ["pe"]="بارگذاری‌تطابق", @@ -4640,7 +4671,7 @@ return { ["cs"]="nastavsynchronizacnilistu", ["de"]="stellesynchronisationsbalkenein", ["en"]="setupsynchronizationbar", - ["fr"]="reglebarresynchronisation", + ["fr"]="configurerbarresynchronisation", ["it"]="impostabarrasincronizzazione", ["nl"]="stelsynchronisatiebalkin", ["pe"]="بارگذاری‌میله‌تطابق", @@ -4650,7 +4681,7 @@ return { ["cs"]="nastavsynonyma", ["de"]="stellesynonymein", ["en"]="setupsynonyms", - ["fr"]="reglesynonymes", + ["fr"]="configurersynonymes", ["it"]="impostasinonimi", ["nl"]="stelsynoniemenin", ["pe"]="بارگذاری‌مترادفها", @@ -4660,7 +4691,7 @@ return { ["cs"]="nastavsystem", ["de"]="stellesystemein", ["en"]="setupsystem", - ["fr"]="reglesysteme", + ["fr"]="configurersysteme", ["it"]="impostasistema", ["nl"]="stelsysteemin", ["pe"]="بارگذاری‌سیستم", @@ -4670,7 +4701,7 @@ return { ["cs"]="nastavtab", ["de"]="stelletabein", ["en"]="setuptab", - ["fr"]="regletab", + ["fr"]="configurertab", ["it"]="impostatab", ["nl"]="steltabin", ["pe"]="بارگذاری‌تب", @@ -4680,7 +4711,7 @@ return { ["cs"]="nastavtabulky", ["de"]="stelletabellenein", ["en"]="setuptables", - ["fr"]="regletableaux", + ["fr"]="configurertables", ["it"]="impostatabelle", ["nl"]="steltabellenin", ["pe"]="بارگذاری‌جدولها", @@ -4690,7 +4721,7 @@ return { ["cs"]="nastavtabelaci", ["de"]="stelletabulatorein", ["en"]="setuptabulate", - ["fr"]="regletabulation", + ["fr"]="configurertabulation", ["it"]="impostatabulato", ["nl"]="steltabulatiein", ["pe"]="بارگذاری‌جدول‌بندی", @@ -4700,7 +4731,7 @@ return { ["cs"]="nastavtext", ["de"]="stelletextein", ["en"]="setuptext", - ["fr"]="regletexte", + ["fr"]="configurertexte", ["it"]="impostatesto", ["nl"]="steltekstin", ["pe"]="بارگذاری‌متن", @@ -4708,13 +4739,14 @@ return { }, ["setuptextbackground"]={ ["en"]="setuptextbackground", + ["fr"]="configurertextearriereplan", ["nl"]="steltekstachtergrondin", }, ["setuptextposition"]={ ["cs"]="setuptextposition", ["de"]="setuptextposition", ["en"]="setuptextposition", - ["fr"]="reglepositiontexte", + ["fr"]="configurerpositiontexte", ["it"]="impostaposizionetesto", ["nl"]="steltekstpositiein", ["pe"]="بارگذاری‌مکان‌متن", @@ -4724,7 +4756,7 @@ return { ["cs"]="nastavtextovelinky", ["de"]="stelletextumrissein", ["en"]="setuptextrules", - ["fr"]="reglelignesreglestexte", + ["fr"]="configurertextetraits", ["it"]="impostalineetesto", ["nl"]="steltekstlijnenin", ["pe"]="بارگذاری‌خطهای‌متن", @@ -4734,7 +4766,7 @@ return { ["cs"]="nastavtexttexty", ["de"]="stelletexttexteein", ["en"]="setuptexttexts", - ["fr"]="regletextestexte", + ["fr"]="configurertextestexte", ["it"]="impostatestotesti", ["nl"]="stelteksttekstenin", ["pe"]="بارگذاری‌متن‌متنها", @@ -4744,7 +4776,7 @@ return { ["cs"]="setuptextvariable", ["de"]="setuptextvariable", ["en"]="setuptextvariable", - ["fr"]="reglevariabletexte", + ["fr"]="configurervariabletexte", ["it"]="impostavariabiletesto", ["nl"]="steltekstvariabelein", ["pe"]="بارگذاری‌متغیر‌متن", @@ -4754,7 +4786,7 @@ return { ["cs"]="nastavtenkelinky", ["de"]="stelleduennerumrissein", ["en"]="setupthinrules", - ["fr"]="regletraitsfins", + ["fr"]="configurertraitsfins", ["it"]="impostalineesottili", ["nl"]="steldunnelijnenin", ["pe"]="بارگذاری‌خطها‌ی‌نازک", @@ -4764,7 +4796,7 @@ return { ["cs"]="nastavtoleranci", ["de"]="stelletoleranzein", ["en"]="setuptolerance", - ["fr"]="regletolerance", + ["fr"]="configurertolerance", ["it"]="impostatolleranza", ["nl"]="steltolerantiein", ["pe"]="بارگذاری‌بردباری", @@ -4774,7 +4806,7 @@ return { ["cs"]="nastavhorejsek", ["de"]="stellenobenein", ["en"]="setuptop", - ["fr"]="reglesup", + ["fr"]="configurerhaut", ["it"]="impostacima", ["nl"]="stelbovenin", ["pe"]="بارگذاری‌بالا", @@ -4784,7 +4816,7 @@ return { ["cs"]="nastavhornitexty", ["de"]="stelletextobenein", ["en"]="setuptoptexts", - ["fr"]="regletextessup", + ["fr"]="configurertexteshaut", ["it"]="impostatesticima", ["nl"]="stelboventekstenin", ["pe"]="بارگذاری‌متنهای‌بالا", @@ -4794,7 +4826,7 @@ return { ["cs"]="nastavtype", ["de"]="stelletipein", ["en"]="setuptype", - ["fr"]="regletype", + ["fr"]="configurertranscrire", ["it"]="impostatype", ["nl"]="steltypein", ["pe"]="بارگذاری‌تایپ", @@ -4804,7 +4836,7 @@ return { ["cs"]="nastavopis", ["de"]="stelletippenein", ["en"]="setuptyping", - ["fr"]="regledactylo", + ["fr"]="configurertranscription", ["it"]="impostatyping", ["nl"]="steltypenin", ["pe"]="بارگذاری‌تایپ‌کردن", @@ -4814,7 +4846,7 @@ return { ["cs"]="nastavpodtrzeni", ["de"]="stelleunterstreichenein", ["en"]="setupunderbar", - ["fr"]="reglesouslignage", + ["fr"]="configurersouligner", ["it"]="impostasottolinea", ["nl"]="stelonderstrepenin", ["pe"]="بارگذاری‌میله‌زیر", @@ -4824,7 +4856,7 @@ return { ["cs"]="nastavurl", ["de"]="stelleurlein", ["en"]="setupurl", - ["fr"]="regleurl", + ["fr"]="configurerurl", ["it"]="impostaurl", ["nl"]="stelurlin", ["pe"]="setupurl", @@ -4834,7 +4866,7 @@ return { ["cs"]="nastavverze", ["de"]="stelleversionein", ["en"]="setupversions", - ["fr"]="regleversions", + ["fr"]="configurerversions", ["it"]="impostaversioni", ["nl"]="stelversiesin", ["pe"]="بارگذاری‌نسخه‌ها", @@ -4844,7 +4876,7 @@ return { ["cs"]="nastavbilamista", ["de"]="stellezwischenraumein", ["en"]="setupwhitespace", - ["fr"]="regleespaceblanc", + ["fr"]="configurerespaceblanc", ["it"]="impostaspaziobianco", ["nl"]="stelwitruimtein", ["pe"]="بارگذاری‌فضای‌سفید", @@ -4854,7 +4886,7 @@ return { ["cs"]="ukazzakladnifont", ["de"]="zeigefliesstext", ["en"]="showbodyfont", - ["fr"]="montrepolicecorps", + ["fr"]="montrerpolicedecorps", ["it"]="mostrafontdeltesto", ["nl"]="toonkorps", ["pe"]="نمایش‌قلم‌بدنه", @@ -4864,7 +4896,7 @@ return { ["cs"]="ukazpostredizakladnihofontu", ["de"]="zeigefliesstextumgebung", ["en"]="showbodyfontenvironment", - ["fr"]="montreenvironnementpolicecorps", + ["fr"]="montrerenvironnementpolicedecorps", ["it"]="mostraambientefontdeltesto", ["nl"]="toonkorpsomgeving", ["pe"]="نمایش‌محیط‌قلم‌بدنه", @@ -4874,7 +4906,7 @@ return { ["cs"]="ukazbarvu", ["de"]="zeigefarbe", ["en"]="showcolor", - ["fr"]="montrecouleur", + ["fr"]="montrercouleur", ["it"]="mostracolore", ["nl"]="toonkleur", ["pe"]="نمایش‌رنگ", @@ -4884,7 +4916,7 @@ return { ["cs"]="ukazskupinubarev", ["de"]="zeigefarbengruppe", ["en"]="showcolorgroup", - ["fr"]="montregroupecouleur", + ["fr"]="montrergroupecouleur", ["it"]="mostragruppocolori", ["nl"]="toonkleurgroep", ["pe"]="نمایش‌گروه‌رنگ", @@ -4894,7 +4926,7 @@ return { ["cs"]="ukazexterniobrazy", ["de"]="zeigeexterneabbildungen", ["en"]="showexternalfigures", - ["fr"]="montrefiguresexternes", + ["fr"]="montrerfiguresexternes", ["it"]="mostrafiguresterne", ["nl"]="toonexternefiguren", ["pe"]="نمایش‌شکلهای‌خارجی", @@ -4904,7 +4936,7 @@ return { ["cs"]="ukazpole", ["de"]="zeigefelder", ["en"]="showfields", - ["fr"]="montrechamps", + ["fr"]="montrerchamps", ["it"]="mostracampi", ["nl"]="toonvelden", ["pe"]="نمایش‌میدانها", @@ -4914,7 +4946,7 @@ return { ["cs"]="ukazramecek", ["de"]="zeigerahmen", ["en"]="showframe", - ["fr"]="montrecadre", + ["fr"]="montrermiseenpage", ["it"]="mostracornice", ["nl"]="toonkader", ["pe"]="نمایش‌قالب", @@ -4924,7 +4956,7 @@ return { ["cs"]="ukazmrizku", ["de"]="zeigegitter", ["en"]="showgrid", - ["fr"]="montregrille", + ["fr"]="montrergrille", ["it"]="mostragriglia", ["nl"]="toongrid", ["pe"]="نمایش‌توری", @@ -4934,7 +4966,7 @@ return { ["cs"]="ukazvzhled", ["de"]="zeigelayout", ["en"]="showlayout", - ["fr"]="montredisposition", + ["fr"]="montrermiseenpage", ["it"]="mostralyout", ["nl"]="toonlayout", ["pe"]="نمایش‌طرح‌بندی", @@ -4944,7 +4976,7 @@ return { ["cs"]="ukazupravu", ["de"]="zeigeumbruch", ["en"]="showmakeup", - ["fr"]="montremakeup", + ["fr"]="montrercomposition", ["it"]="mostramakeup", ["nl"]="toonopmaak", ["pe"]="نمایش‌آرایش", @@ -4954,7 +4986,7 @@ return { ["cs"]="ukazpaletu", ["de"]="zeigepalette", ["en"]="showpalet", - ["fr"]="montrepalette", + ["fr"]="montrerpalette", ["it"]="mostratavolozza", ["nl"]="toonpalet", ["pe"]="نمایش‌لوح", @@ -4964,7 +4996,7 @@ return { ["cs"]="ukazvytisk", ["de"]="zeigedruck", ["en"]="showprint", - ["fr"]="montreedition", + ["fr"]="montrerimpression", ["it"]="mostrastampa", ["nl"]="toonprint", ["pe"]="نمایش‌چاپ", @@ -4974,7 +5006,7 @@ return { ["cs"]="ukaznastaveni", ["de"]="zeigeeinstellungen", ["en"]="showsetups", - ["fr"]="montrereglages", + ["fr"]="montrerconfigurations", ["it"]="mostraimpostazioni", ["nl"]="tooninstellingen", ["pe"]="نمایش‌بارگذاریها", @@ -4984,7 +5016,7 @@ return { ["cs"]="ukazpodpery", ["de"]="zeigestruts", ["en"]="showstruts", - ["fr"]="montrestruts", + ["fr"]="montrerentretoises", ["it"]="mostrastruts", ["nl"]="toonstruts", ["pe"]="نمایش‌بستها", @@ -4994,7 +5026,7 @@ return { ["cs"]="ukazsadusymbolu", ["de"]="showsymbolset", ["en"]="showsymbolset", - ["fr"]="montrejeusymboles", + ["fr"]="montrerjeusymboles", ["it"]="mostrasetsimboli", ["nl"]="toonsymboolset", ["pe"]="نمایش‌مجموعه‌علامت", @@ -5004,7 +5036,7 @@ return { ["cs"]="kap", ["de"]="kap", ["en"]="cap", - ["fr"]="cap", + ["fr"]="petitescap", ["it"]="cap", ["nl"]="kap", ["pe"]="cap", @@ -5044,7 +5076,7 @@ return { ["cs"]="rozdelplvouciobjekt", ["de"]="teilegleitobjekt", ["en"]="splitfloat", - ["fr"]="separeflottant", + ["fr"]="flottantpartage", ["it"]="spezzaoggettomobile", ["nl"]="splitsplaatsblok", ["pe"]="شکافتن‌شناور", @@ -5054,21 +5086,17 @@ return { ["cs"]="startzarovnavani", ["de"]="startausrichtung", ["en"]="startalignment", - ["fr"]="demarrealignement", + ["fr"]="débutalignement", ["it"]="iniziaallineamento", ["nl"]="startuitlijnen", ["pe"]="شروع‌تنظیم", ["ro"]="startaliniere", }, - ["alignment"]={ - ["en"]="alignment", - ["nl"]="uitlijnen", - }, ["startbackground"]={ ["cs"]="startpozadi", ["de"]="starthintergrund", ["en"]="startbackground", - ["fr"]="demarrearriereplan", + ["fr"]="débutarriereplan", ["it"]="iniziasfondo", ["nl"]="startachtergrond", ["pe"]="شروع‌پس‌زمینه", @@ -5078,7 +5106,7 @@ return { ["cs"]="startkodovani", ["de"]="startkodierung", ["en"]="startcoding", - ["fr"]="demarrecodage", + ["fr"]="débutcodage", ["it"]="iniziacodifica", ["nl"]="startcodering", ["pe"]="شروع‌کد", @@ -5088,7 +5116,7 @@ return { ["cs"]="startbarva", ["de"]="startfarbe", ["en"]="startcolor", - ["fr"]="demarrecouleur", + ["fr"]="débutcouleur", ["it"]="iniziacolore", ["nl"]="startkleur", ["pe"]="شروع‌رنگ", @@ -5098,7 +5126,7 @@ return { ["cs"]="startcolumnmakeup", ["de"]="startcolumnmakeup", ["en"]="startcolumnmakeup", - ["fr"]="startcolumnmakeup", + ["fr"]="débutcompositioncolonne", ["it"]="startcolumnmakeup", ["nl"]="startkolomopmaak", ["pe"]="شروع‌آرایش‌ستون", @@ -5108,7 +5136,7 @@ return { ["cs"]="startsloupce", ["de"]="startspalten", ["en"]="startcolumns", - ["fr"]="demarrecolonnes", + ["fr"]="débutcolonnes", ["it"]="iniziacolonne", ["nl"]="startkolommen", ["pe"]="شروع‌ستونها", @@ -5118,7 +5146,7 @@ return { ["cs"]="startcolumnset", ["de"]="startcolumnset", ["en"]="startcolumnset", - ["fr"]="demarrejeucolonne", + ["fr"]="débutjeucolonnes", ["it"]="iniziagruppocolonne", ["nl"]="startkolomgroep", ["pe"]="شروع‌مجموعه‌ستون", @@ -5128,7 +5156,7 @@ return { ["cs"]="startspojeni", ["de"]="startkombination", ["en"]="startcombination", - ["fr"]="demarrecombinaison", + ["fr"]="débutcombinaison", ["it"]="iniziacombinazione", ["nl"]="startcombinatie", ["pe"]="شروع‌ترکیب", @@ -5138,7 +5166,7 @@ return { ["cs"]="startkomponenta", ["de"]="startkomponente", ["en"]="startcomponent", - ["fr"]="demarrecomposant", + ["fr"]="débutcomposant", ["it"]="iniziacomponente", ["nl"]="startonderdeel", ["pe"]="شروع‌مولفه", @@ -5148,7 +5176,7 @@ return { ["cs"]="startdokument", ["de"]="startdokument", ["en"]="startdocument", - ["fr"]="demarredocument", + ["fr"]="débutdocument", ["it"]="iniziadocumento", ["nl"]="startdocument", ["pe"]="شروع‌نوشتار", @@ -5158,7 +5186,7 @@ return { ["cs"]="startprostredi", ["de"]="startumgebung", ["en"]="startenvironment", - ["fr"]="demarreenvironement", + ["fr"]="débutenvironnement", ["it"]="iniziaambiente", ["nl"]="startomgeving", ["pe"]="شروع‌محیط", @@ -5168,7 +5196,7 @@ return { ["cs"]="startobraz", ["de"]="startabbildung", ["en"]="startfigure", - ["fr"]="demarrefigure", + ["fr"]="débutfigure", ["it"]="iniziafigura", ["nl"]="startfiguur", ["pe"]="شروع‌شکل", @@ -5176,13 +5204,14 @@ return { }, ["startframed"]={ ["en"]="startframed", + ["fr"]="débutencadre", ["nl"]="startomlijnd", }, ["startglobal"]={ ["cs"]="startglobalni", ["de"]="startglobal", ["en"]="startglobal", - ["fr"]="demarreglobal", + ["fr"]="débutglobal", ["it"]="iniziaglobale", ["nl"]="startglobaal", ["pe"]="شروع‌سراسری", @@ -5192,7 +5221,7 @@ return { ["cs"]="startradek", ["de"]="startzeile", ["en"]="startline", - ["fr"]="demarreligne", + ["fr"]="débutligneref", ["it"]="iniziariga", ["nl"]="startregel", ["pe"]="شروع‌خط", @@ -5202,21 +5231,17 @@ return { ["cs"]="startkorekceradku", ["de"]="startzeilenkorrektur", ["en"]="startlinecorrection", - ["fr"]="demarrecorrectionligne", + ["fr"]="débutcorrectionligne", ["it"]="iniziacorrezioneriga", ["nl"]="startregelcorrectie", ["pe"]="شروع‌تصحیح‌خط", ["ro"]="startcorectielinie", }, - ["linecorrection"]={ - ["en"]="linecorrection", - ["nl"]="regelcorrectie", - }, ["startlinenumbering"]={ ["cs"]="startcislovaniradku", ["de"]="startzeilennumerierung", ["en"]="startlinenumbering", - ["fr"]="demarrenumerotationligne", + ["fr"]="débutnumérotationligne", ["it"]="inizianumerazionerighe", ["nl"]="startregelnummeren", ["pe"]="شروع‌شماره‌گذاری‌خط", @@ -5226,7 +5251,7 @@ return { ["cs"]="startradky", ["de"]="startzeilen", ["en"]="startlines", - ["fr"]="demarrelignes", + ["fr"]="débutlignes", ["it"]="iniziarighe", ["nl"]="startregels", ["pe"]="شروع‌خطها", @@ -5236,7 +5261,7 @@ return { ["cs"]="startlokalni", ["de"]="startlokal", ["en"]="startlocal", - ["fr"]="demarrelocal", + ["fr"]="débutlocal", ["it"]="inizialocale", ["nl"]="startlokaal", ["pe"]="شروع‌موضعی", @@ -5246,21 +5271,17 @@ return { ["cs"]="startlokalnipoznamkypodcarou", ["de"]="startlokalefussnoten", ["en"]="startlocalfootnotes", - ["fr"]="demarrenotespdplocales", + ["fr"]="débutnotesbdplocal", ["it"]="inizianotepdplocali", ["nl"]="startlokalevoetnoten", ["pe"]="شروع‌پانوشتهای‌موضعی", ["ro"]="startnotesubsollocale", }, - ["localfootnotes"]={ - ["en"]="localfootnotes", - ["nl"]="lokalevoetnoten", - }, ["startmakeup"]={ ["cs"]="startuprava", ["de"]="startumbruch", ["en"]="startmakeup", - ["fr"]="demarremakeup", + ["fr"]="débutcomposition", ["it"]="iniziamakeup", ["nl"]="startopmaak", ["pe"]="شروع‌آرایش", @@ -5270,21 +5291,17 @@ return { ["cs"]="startmarginalniblok", ["de"]="startmarginalblock", ["en"]="startmarginblock", - ["fr"]="demarreblocmarge", + ["fr"]="débutblocmarge", ["it"]="iniziabloccomargine", ["nl"]="startmargeblok", ["pe"]="شروع‌بلوک‌حاشیه", ["ro"]="startblocmarginal", }, - ["marginblock"]={ - ["en"]="marginblock", - ["nl"]="margeblok", - }, ["startmarginrule"]={ ["cs"]="startmarginalnilinka", ["de"]="startmarginallinie", ["en"]="startmarginrule", - ["fr"]="demarremargereglee", + ["fr"]="débuttraitmarge", ["it"]="inizialineamargine", ["nl"]="startkantlijn", ["pe"]="شروع‌خط‌حاشیه", @@ -5294,7 +5311,7 @@ return { ["cs"]="startzuzeni", ["de"]="startenger", ["en"]="startnarrower", - ["fr"]="demarrecompoetroite", + ["fr"]="débutplusetroit", ["it"]="iniziapiustretto", ["nl"]="startsmaller", ["pe"]="شروع‌باریکتر", @@ -5304,7 +5321,7 @@ return { ["cs"]="startprotejsek", ["de"]="startgegenueber", ["en"]="startopposite", - ["fr"]="demarreopposition", + ["fr"]="débutopposition", ["it"]="iniziaopposto", ["nl"]="startnaast", ["pe"]="شروع‌مخالف", @@ -5314,7 +5331,7 @@ return { ["cs"]="startprekryv", ["de"]="startoverlay", ["en"]="startoverlay", - ["fr"]="demarrerevetement", + ["fr"]="débutsuperposition", ["it"]="iniziasovrapposizione", ["nl"]="startoverlay", ["pe"]="شروع‌پوشش", @@ -5324,7 +5341,7 @@ return { ["cs"]="startprehled", ["de"]="startueberblick", ["en"]="startoverview", - ["fr"]="demarrevuedensemble", + ["fr"]="débutvuedensemble", ["it"]="iniziaoverview", ["nl"]="startoverzicht", ["pe"]="شروع‌بازبینی", @@ -5334,7 +5351,7 @@ return { ["cs"]="startzhustene", ["de"]="startkleinerdurchschuss", ["en"]="startpacked", - ["fr"]="demarregroupe", + ["fr"]="débutemballage", ["it"]="iniziaimpaccato", ["nl"]="startopelkaar", ["pe"]="شروع‌فشرده", @@ -5344,7 +5361,7 @@ return { ["cs"]="startumistovani", ["de"]="startpositionieren", ["en"]="startpositioning", - ["fr"]="demarrepositionnement", + ["fr"]="débutpositionnement", ["it"]="iniziaposizionamento", ["nl"]="startpositioneren", ["pe"]="شروع‌مکان‌گذاری", @@ -5354,7 +5371,7 @@ return { ["cs"]="startprodukt", ["de"]="startprodukt", ["en"]="startproduct", - ["fr"]="demarreproduit", + ["fr"]="débutproduit", ["it"]="iniziaprodotto", ["nl"]="startprodukt", ["pe"]="شروع‌تولید", @@ -5364,7 +5381,7 @@ return { ["cs"]="startprofil", ["de"]="startprofil", ["en"]="startprofile", - ["fr"]="demarreprofil", + ["fr"]="débutprofil", ["it"]="iniziaprofilo", ["nl"]="startprofiel", ["pe"]="شروع‌پروفایل", @@ -5374,7 +5391,7 @@ return { ["cs"]="startprojekt", ["de"]="startprojekt", ["en"]="startproject", - ["fr"]="demarreprojet", + ["fr"]="débutprojet", ["it"]="iniziaprogetto", ["nl"]="startprojekt", ["pe"]="شروع‌پروژه", @@ -5384,7 +5401,7 @@ return { ["cs"]="startcitace", ["de"]="startzitat", ["en"]="startquotation", - ["fr"]="demarrecitation", + ["fr"]="débutcitation", ["it"]="iniziacitazione", ["nl"]="startcitaat", ["pe"]="شروع‌نقل‌قول", @@ -5394,7 +5411,7 @@ return { ["cs"]="startrastr", ["de"]="startraster", ["en"]="startraster", - ["fr"]="demarreraster", + ["fr"]="débutraster", ["it"]="iniziaraster", ["nl"]="startraster", ["pe"]="startraster", @@ -5404,7 +5421,7 @@ return { ["cs"]="startsadasymbolu", ["de"]="startsymbolset", ["en"]="startsymbolset", - ["fr"]="demarrejeusymboles", + ["fr"]="débutjeusymboles", ["it"]="iniziasetsimboli", ["nl"]="startsymboolset", ["pe"]="شروع‌مجموعه‌نماد", @@ -5414,7 +5431,7 @@ return { ["cs"]="startsynchronizace", ["de"]="startsynchronisation", ["en"]="startsynchronization", - ["fr"]="demarresynchronisation", + ["fr"]="débutsynchronisation", ["it"]="iniziasincronizzazione", ["nl"]="startsynchronisatie", ["pe"]="شروع‌تطابق", @@ -5424,7 +5441,7 @@ return { ["cs"]="starttabulka", ["de"]="starttabelle", ["en"]="starttable", - ["fr"]="demarretableau", + ["fr"]="débuttable", ["it"]="iniziatabella", ["nl"]="starttabel", ["pe"]="شروع‌جدول", @@ -5434,7 +5451,7 @@ return { ["cs"]="starttabulky", ["de"]="starttabellen", ["en"]="starttables", - ["fr"]="demarretableaux", + ["fr"]="débuttables", ["it"]="iniziatabelle", ["nl"]="starttabellen", ["pe"]="شروع‌جدولها", @@ -5444,7 +5461,7 @@ return { ["cs"]="starttext", ["de"]="starttext", ["en"]="starttext", - ["fr"]="demarretexte", + ["fr"]="débuttexte", ["it"]="iniziatesto", ["nl"]="starttekst", ["pe"]="شروع‌متن", @@ -5452,17 +5469,14 @@ return { }, ["starttextbackground"]={ ["en"]="starttextbackground", + ["fr"]="débuttextearriereplan", ["nl"]="starttekstachtergrond", }, - ["textbackground"]={ - ["en"]="textbackground", - ["nl"]="tekstachtergrond", - }, ["starttextrule"]={ ["cs"]="starttextovalinka", ["de"]="starttextlinie", ["en"]="starttextrule", - ["fr"]="demarreligneregleetexte", + ["fr"]="débuttextetrait", ["it"]="inizialineatesto", ["nl"]="starttekstlijn", ["pe"]="شروع‌خط‌متن", @@ -5472,7 +5486,7 @@ return { ["cs"]="startnezhustene", ["de"]="startgrosserdurchschuss", ["en"]="startunpacked", - ["fr"]="demarredegroupe", + ["fr"]="débutdesemballage", ["it"]="iniziaunpacked", ["nl"]="startvanelkaar", ["pe"]="شروع‌غیر‌فشرده", @@ -5482,7 +5496,7 @@ return { ["cs"]="startverze", ["de"]="startversion", ["en"]="startversion", - ["fr"]="demarreversion", + ["fr"]="débutversion", ["it"]="iniziaversione", ["nl"]="startversie", ["pe"]="شروع‌نسخه", @@ -5492,7 +5506,7 @@ return { ["cs"]="stopzarovnavani", ["de"]="stopausrichtung", ["en"]="stopalignment", - ["fr"]="stoppealignement", + ["fr"]="finalignement", ["it"]="terminaallineamento", ["nl"]="stopuitlijnen", ["pe"]="پایان‌تنظیم", @@ -5502,7 +5516,7 @@ return { ["cs"]="stoppozadi", ["de"]="stophintergrund", ["en"]="stopbackground", - ["fr"]="stoppearriereplan", + ["fr"]="finarriereplan", ["it"]="terminasfondo", ["nl"]="stopachtergrond", ["pe"]="پایان‌پس‌زمینه", @@ -5512,7 +5526,7 @@ return { ["cs"]="stopkodovani", ["de"]="stopkodierung", ["en"]="stopcoding", - ["fr"]="stoppecodage", + ["fr"]="fincodage", ["it"]="terminacodifica", ["nl"]="stopcodering", ["pe"]="پایان‌کد", @@ -5522,7 +5536,7 @@ return { ["cs"]="stopbarva", ["de"]="stopfarbe", ["en"]="stopcolor", - ["fr"]="stoppecouleur", + ["fr"]="fincouleur", ["it"]="terminacolore", ["nl"]="stopkleur", ["pe"]="پایان‌رنگ", @@ -5532,7 +5546,7 @@ return { ["cs"]="stopcolumnmakeup", ["de"]="stopcolumnmakeup", ["en"]="stopcolumnmakeup", - ["fr"]="stopcolumnmakeup", + ["fr"]="fincompositioncolonne", ["it"]="stopcolumnmakeup", ["nl"]="stopkolomopmaak", ["pe"]="پایان‌آرایش‌ستون", @@ -5542,7 +5556,7 @@ return { ["cs"]="stopsloupce", ["de"]="stopspalten", ["en"]="stopcolumns", - ["fr"]="stoppecolonnes", + ["fr"]="fincolonnes", ["it"]="terminacolonne", ["nl"]="stopkolommen", ["pe"]="پایان‌ستونها", @@ -5552,7 +5566,7 @@ return { ["cs"]="stopcolumnset", ["de"]="stopcolumnset", ["en"]="stopcolumnset", - ["fr"]="stoppejeucolonne", + ["fr"]="finjeucolonnes", ["it"]="terminagruppocolonne", ["nl"]="stopkolomgroep", ["pe"]="پایان‌مجموعه‌ستون", @@ -5562,7 +5576,7 @@ return { ["cs"]="stopspojeni", ["de"]="stopkombination", ["en"]="stopcombination", - ["fr"]="stoppecombinaison", + ["fr"]="fincombinaison", ["it"]="terminacombinazione", ["nl"]="stopcombinatie", ["pe"]="پایان‌ترکیب", @@ -5572,7 +5586,7 @@ return { ["cs"]="stopkomponenta", ["de"]="stopkomponente", ["en"]="stopcomponent", - ["fr"]="stoppecomposant", + ["fr"]="fincomposant", ["it"]="terminacomponente", ["nl"]="stoponderdeel", ["pe"]="پایان‌مولفه", @@ -5582,7 +5596,7 @@ return { ["cs"]="stopdokument", ["de"]="stopdokument", ["en"]="stopdocument", - ["fr"]="stoppedocument", + ["fr"]="findocument", ["it"]="terminadocumento", ["nl"]="stopdocument", ["pe"]="پایان‌نوشتار", @@ -5592,7 +5606,7 @@ return { ["cs"]="stopprostredi", ["de"]="stopumgebung", ["en"]="stopenvironment", - ["fr"]="stoppeenvironement", + ["fr"]="finenvironnement", ["it"]="terminaambiente", ["nl"]="stopomgeving", ["pe"]="پایان‌محیط", @@ -5600,13 +5614,14 @@ return { }, ["stopframed"]={ ["en"]="stopframed", + ["fr"]="finencadre", ["nl"]="stopomlijnd", }, ["stopglobal"]={ ["cs"]="stopglobalni", ["de"]="stopglobal", ["en"]="stopglobal", - ["fr"]="stoppeglobal", + ["fr"]="finglobal", ["it"]="terminaglobale", ["nl"]="stopglobaal", ["pe"]="پایان‌سراسری", @@ -5616,7 +5631,7 @@ return { ["cs"]="stopradek", ["de"]="stopzeile", ["en"]="stopline", - ["fr"]="stoppeligne", + ["fr"]="finligneref", ["it"]="terminariga", ["nl"]="stopregel", ["pe"]="پایان‌خط", @@ -5626,7 +5641,7 @@ return { ["cs"]="stopkorekceradku", ["de"]="stopzeilenkorrektur", ["en"]="stoplinecorrection", - ["fr"]="stoppecorrectionligne", + ["fr"]="fincorrectionligne", ["it"]="terminacorrezioneriga", ["nl"]="stopregelcorrectie", ["pe"]="پایان‌تصحیح‌خط", @@ -5636,7 +5651,7 @@ return { ["cs"]="stopcislovaniradku", ["de"]="stopzeilennumerierung", ["en"]="stoplinenumbering", - ["fr"]="stoppenumerotationligne", + ["fr"]="finnumérotationligne", ["it"]="terminanumerazionerighe", ["nl"]="stopregelnummeren", ["pe"]="پایان‌شماره‌گذاری‌خط", @@ -5646,7 +5661,7 @@ return { ["cs"]="stopradky", ["de"]="stopzeilen", ["en"]="stoplines", - ["fr"]="stoppelignes", + ["fr"]="finlignes", ["it"]="terminarighe", ["nl"]="stopregels", ["pe"]="پایان‌خطها", @@ -5656,7 +5671,7 @@ return { ["cs"]="stoplokalni", ["de"]="stoplokal", ["en"]="stoplocal", - ["fr"]="stoppelocal", + ["fr"]="finlocal", ["it"]="terminalocale", ["nl"]="stoplokaal", ["pe"]="پایان‌موضعی", @@ -5666,7 +5681,7 @@ return { ["cs"]="stoplokalnipoznamkypodcarou", ["de"]="stoplokalefussnoten", ["en"]="stoplocalfootnotes", - ["fr"]="stoppenotespdplocales", + ["fr"]="finnotesbdplocal", ["it"]="terminanotepdplocali", ["nl"]="stoplokalevoetnoten", ["pe"]="پایان‌پانوشتهای‌موضعی", @@ -5676,7 +5691,7 @@ return { ["cs"]="stopuprava", ["de"]="stopumbruch", ["en"]="stopmakeup", - ["fr"]="stoppemakeup", + ["fr"]="fincomposition", ["it"]="terminamakeup", ["nl"]="stopopmaak", ["pe"]="پایان‌آرایش", @@ -5686,7 +5701,7 @@ return { ["cs"]="stopmarginalniblok", ["de"]="stopmarginalblock", ["en"]="stopmarginblock", - ["fr"]="stoppeblocmarge", + ["fr"]="finblocmarge", ["it"]="terminabloccomargine", ["nl"]="stopmargeblok", ["pe"]="پایان‌بلوک‌حاشیه", @@ -5696,7 +5711,7 @@ return { ["cs"]="stopmarginalnilinka", ["de"]="stopmarginallinie", ["en"]="stopmarginrule", - ["fr"]="stoppemargereglee", + ["fr"]="fintraitmarge", ["it"]="terminalineamargine", ["nl"]="stopkantlijn", ["pe"]="پایان‌خط‌حاشیه", @@ -5706,7 +5721,7 @@ return { ["cs"]="stopzuzeni", ["de"]="stopenger", ["en"]="stopnarrower", - ["fr"]="stopcompoetroite", + ["fr"]="finplusetroit", ["it"]="terminapiustretto", ["nl"]="stopsmaller", ["pe"]="پایان‌نازکتر", @@ -5716,7 +5731,7 @@ return { ["cs"]="stopprotejsek", ["de"]="stopgegenueber", ["en"]="stopopposite", - ["fr"]="stoppeopposition", + ["fr"]="finopposition", ["it"]="terminaopposto", ["nl"]="stopnaast", ["pe"]="پایان‌مخالف", @@ -5726,7 +5741,7 @@ return { ["cs"]="stopprekryv", ["de"]="stopoverlay", ["en"]="stopoverlay", - ["fr"]="stopperevetement", + ["fr"]="finsuperposition", ["it"]="terminasovrapposizione", ["nl"]="stopoverlay", ["pe"]="پایان‌پوشش", @@ -5736,7 +5751,7 @@ return { ["cs"]="stopprehled", ["de"]="stopueberblick", ["en"]="stopoverview", - ["fr"]="stoppevuedensemble", + ["fr"]="finvuedensemble", ["it"]="terminaoverview", ["nl"]="stopoverzicht", ["pe"]="پایان‌بازبینی", @@ -5746,7 +5761,7 @@ return { ["cs"]="stopzhustene", ["de"]="stopkleinerdurchschuss", ["en"]="stoppacked", - ["fr"]="stoppegroupe", + ["fr"]="finemballage", ["it"]="terminaimpaccato", ["nl"]="stopopelkaar", ["pe"]="پایان‌فشرده", @@ -5756,7 +5771,7 @@ return { ["cs"]="stopumistovani", ["de"]="stoppositionieren", ["en"]="stoppositioning", - ["fr"]="stoppepositionnement", + ["fr"]="finpositionnement", ["it"]="terminaposizionamento", ["nl"]="stoppositioneren", ["pe"]="پایان‌مکان‌گذاری", @@ -5766,7 +5781,7 @@ return { ["cs"]="stopprodukt", ["de"]="stopprodukt", ["en"]="stopproduct", - ["fr"]="stoppeproduit", + ["fr"]="finproduit", ["it"]="terminaprodotto", ["nl"]="stopprodukt", ["pe"]="پایان‌تولید", @@ -5776,7 +5791,7 @@ return { ["cs"]="stopprofil", ["de"]="stopprofil", ["en"]="stopprofile", - ["fr"]="stoppeprofil", + ["fr"]="finprofil", ["it"]="terminaprofili", ["nl"]="stopprofiel", ["pe"]="پایان‌پروفایل", @@ -5786,7 +5801,7 @@ return { ["cs"]="stopprojekt", ["de"]="stopprojekt", ["en"]="stopproject", - ["fr"]="stoppeprojet", + ["fr"]="finprojet", ["it"]="terminaprogetto", ["nl"]="stopprojekt", ["pe"]="پایان‌پروژه", @@ -5796,7 +5811,7 @@ return { ["cs"]="stopcitace", ["de"]="stopzitat", ["en"]="stopquotation", - ["fr"]="stoppecitation", + ["fr"]="fincitation", ["it"]="terminacitazione", ["nl"]="stopcitaat", ["pe"]="پایان‌نقل‌قول", @@ -5806,7 +5821,7 @@ return { ["cs"]="stoprastr", ["de"]="stopraster", ["en"]="stopraster", - ["fr"]="stopperaster", + ["fr"]="finraster", ["it"]="terminaraster", ["nl"]="stopraster", ["pe"]="stopraster", @@ -5816,7 +5831,7 @@ return { ["cs"]="stopsynchronizace", ["de"]="stopsynchronisation", ["en"]="stopsynchronization", - ["fr"]="stoppesynchronisation", + ["fr"]="finsynchronisation", ["it"]="terminasincronizzazione", ["nl"]="stopsynchronisatie", ["pe"]="پایان‌تطابق", @@ -5826,7 +5841,7 @@ return { ["cs"]="stoptabulka", ["de"]="stoptabelle", ["en"]="stoptable", - ["fr"]="stoppetableau", + ["fr"]="fintable", ["it"]="terminatabella", ["nl"]="stoptabel", ["pe"]="پایان‌جدول", @@ -5836,7 +5851,7 @@ return { ["cs"]="stoptabulky", ["de"]="stoptabellen", ["en"]="stoptables", - ["fr"]="stoppetableaux", + ["fr"]="fintables", ["it"]="terminatabelle", ["nl"]="stoptabellen", ["pe"]="پایان‌جدولها", @@ -5846,7 +5861,7 @@ return { ["cs"]="stoptext", ["de"]="stoptext", ["en"]="stoptext", - ["fr"]="stoppetexte", + ["fr"]="fintexte", ["it"]="terminatesto", ["nl"]="stoptekst", ["pe"]="پایان‌متن", @@ -5854,13 +5869,14 @@ return { }, ["stoptextbackground"]={ ["en"]="stoptextbackground", + ["fr"]="fintextearriereplan", ["nl"]="stoptekstachtergrond", }, ["stoptextrule"]={ ["cs"]="stoptextovalinka", ["de"]="stoptextlinie", ["en"]="stoptextrule", - ["fr"]="stoppeligneregleetexte", + ["fr"]="fintextetrait", ["it"]="terminalineatesto", ["nl"]="stoptekstlijn", ["pe"]="پایان‌خط‌متن", @@ -5870,7 +5886,7 @@ return { ["cs"]="stopnezhustene", ["de"]="stopgrosserdurchschuss", ["en"]="stopunpacked", - ["fr"]="stoppedegroupe", + ["fr"]="findesemballage", ["it"]="terminaunpacked", ["nl"]="stopvanelkaar", ["pe"]="پایان‌غیرفشرده", @@ -5880,7 +5896,7 @@ return { ["cs"]="stopverze", ["de"]="stopversion", ["en"]="stopversion", - ["fr"]="stoppeversion", + ["fr"]="finversion", ["it"]="terminaversioni", ["nl"]="stopversie", ["pe"]="پایان‌نسخه", @@ -5910,7 +5926,7 @@ return { ["cs"]="subpagenumber", ["de"]="subpagenumber", ["en"]="subpagenumber", - ["fr"]="sousnumeropage", + ["fr"]="numerosouspage", ["it"]="subpagenumber", ["nl"]="subpaginanummer", ["pe"]="شماره‌زیرصفحه", @@ -5920,7 +5936,7 @@ return { ["cs"]="prepninazakladnifont", ["de"]="wechselezumfliesstext", ["en"]="switchtobodyfont", - ["fr"]="changepolicecorps", + ["fr"]="passerapolicedecorps", ["it"]="cambiaafontdeltesto", ["nl"]="switchnaarkorps", ["pe"]="تغییربه‌قلم‌بدنه", @@ -5930,7 +5946,7 @@ return { ["cs"]="switchtorawfont", ["de"]="switchtorawfont", ["en"]="switchtorawfont", - ["fr"]="changepolicebrute", + ["fr"]="passerapolicebrute", ["it"]="passaafontgrezzo", ["nl"]="switchtorawfont", ["pe"]="تغییربه‌قلم‌خام", @@ -5958,6 +5974,7 @@ return { }, ["symoffset"]={ ["en"]="symoffset", + ["fr"]="decalagesym", ["nl"]="symoffset", }, ["synchronizationbar"]={ @@ -5974,7 +5991,7 @@ return { ["cs"]="synchronizovat", ["de"]="synchronisieren", ["en"]="synchronize", - ["fr"]="synchronise", + ["fr"]="synchroniser", ["it"]="sincronizza", ["nl"]="synchroniseer", ["pe"]="تطابق", @@ -5994,7 +6011,7 @@ return { ["cs"]="testcolumn", ["de"]="testcolumn", ["en"]="testcolumn", - ["fr"]="testcolumn", + ["fr"]="testcolonne", ["it"]="testcolumn", ["nl"]="testkolom", ["pe"]="ستون‌امتحان", @@ -6020,6 +6037,11 @@ return { ["pe"]="تک", ["ro"]="tex", }, + ["textbackground"]={ + ["en"]="textbackground", + ["fr"]="textearriereplan", + ["nl"]="tekstachtergrond", + }, ["textheight"]={ ["cs"]="vyskatextu", ["de"]="texthoehe", @@ -6044,7 +6066,7 @@ return { ["cs"]="textovalinka", ["de"]="textlinie", ["en"]="textrule", - ["fr"]="ligneregleetexte", + ["fr"]="traittexte", ["it"]="lineatesto", ["nl"]="tekstlijn", ["pe"]="خط‌متن", @@ -6094,7 +6116,7 @@ return { ["cs"]="bublinkovanapoveda", ["de"]="tooltip", ["en"]="tooltip", - ["fr"]="suggestion", + ["fr"]="infobulle", ["it"]="tooltip", ["nl"]="suggestie", ["pe"]="tooltip", @@ -6104,7 +6126,7 @@ return { ["cs"]="vzdalenosthorejsku", ["de"]="abstandoben", ["en"]="topdistance", - ["fr"]="distancesup", + ["fr"]="distancehaut", ["it"]="distanzacima", ["nl"]="bovenafstand", ["pe"]="فاصله‌بالا", @@ -6114,7 +6136,7 @@ return { ["cs"]="vyskahorejsku", ["de"]="hoeheoben", ["en"]="topheight", - ["fr"]="hauteursup", + ["fr"]="hauteurhaut", ["it"]="altezzacima", ["nl"]="bovenhoogte", ["pe"]="ارتفاع‌بالا", @@ -6124,7 +6146,7 @@ return { ["cs"]="odsazenishora", ["de"]="kopfweite", ["en"]="topspace", - ["fr"]="espacesup", + ["fr"]="espacehaut", ["it"]="spaziocima", ["nl"]="kopwit", ["pe"]="فضای‌بالا", @@ -6164,7 +6186,7 @@ return { ["cs"]="pis", ["de"]="tip", ["en"]="typ", - ["fr"]="typ", + ["fr"]="transcrireaveccesure", ["it"]="typ", ["nl"]="typ", ["pe"]="typ", @@ -6174,7 +6196,7 @@ return { ["cs"]="opis", ["de"]="tippen", ["en"]="type", - ["fr"]="dactylographier", + ["fr"]="transcrire", ["it"]="type", ["nl"]="type", ["pe"]="تایپ", @@ -6184,7 +6206,7 @@ return { ["cs"]="typebuffer", ["de"]="tippepuffer", ["en"]="typebuffer", - ["fr"]="tapebuffer", + ["fr"]="transcriretampon", ["it"]="typebuffer", ["nl"]="typebuffer", ["pe"]="تایپ‌بافر", @@ -6194,7 +6216,7 @@ return { ["cs"]="opissoubor", ["de"]="tippedatei", ["en"]="typefile", - ["fr"]="fichierdactylo", + ["fr"]="transcrirefichier", ["it"]="typefile", ["nl"]="typefile", ["pe"]="تایپ‌پرونده", @@ -6204,7 +6226,7 @@ return { ["cs"]="vyznam", ["de"]="bedeutung", ["en"]="unitmeaning", - ["fr"]="sensunite", + ["fr"]="significationunite", ["it"]="nomeunita", ["nl"]="betekenis", ["pe"]="معنی‌واحد", @@ -6224,7 +6246,7 @@ return { ["cs"]="uzijJSscripts", ["de"]="verwendeJSscript", ["en"]="useJSscripts", - ["fr"]="utiliseJSscripts", + ["fr"]="utiliserJSscript", ["it"]="usaJSscripts", ["nl"]="gebruikJSscripts", ["pe"]="useJSscripts", @@ -6234,7 +6256,7 @@ return { ["cs"]="uzijURL", ["de"]="verwendeURL", ["en"]="useURL", - ["fr"]="utiliseURL", + ["fr"]="utiliserURL", ["it"]="usaURL", ["nl"]="gebruikURL", ["pe"]="useURL", @@ -6244,7 +6266,7 @@ return { ["cs"]="useXMLfilter", ["de"]="useXMLfilter", ["en"]="useXMLfilter", - ["fr"]="useXMLfilter", + ["fr"]="utiliserfiltreXML", ["it"]="useXMLfilter", ["nl"]="gebruikXMLfilter", ["pe"]="useXMLfilter", @@ -6254,7 +6276,7 @@ return { ["cs"]="uzijbloky", ["de"]="verwendebloecke", ["en"]="useblocks", - ["fr"]="utiliseblocs", + ["fr"]="utiliserblocs", ["it"]="usablocco", ["nl"]="gebruikblokken", ["pe"]="استفاده‌بلوکها", @@ -6264,7 +6286,7 @@ return { ["cs"]="uzijprikazy", ["de"]="verwendebefehl", ["en"]="usecommands", - ["fr"]="utilisecommandes", + ["fr"]="utilisercommandes", ["it"]="usacomandi", ["nl"]="gebruikcommandos", ["pe"]="استفاده‌فرمانها", @@ -6274,7 +6296,7 @@ return { ["cs"]="uzijkodovani", ["de"]="benutzekodierung", ["en"]="useencoding", - ["fr"]="utiliseencodage", + ["fr"]="utilisercodage", ["it"]="usacodifica", ["nl"]="usecodering", ["pe"]="استفاده‌رمزینه", @@ -6284,7 +6306,7 @@ return { ["cs"]="uzijexternidokument", ["de"]="verwendeexteresdokument", ["en"]="useexternaldocument", - ["fr"]="utilisedocumentexterne", + ["fr"]="utiliserdocumentexterne", ["it"]="usadocumentoesterno", ["nl"]="gebruikexterndocument", ["pe"]="استفاده‌نوشتارخارجی", @@ -6294,7 +6316,7 @@ return { ["cs"]="uzijexterniobraz", ["de"]="verwendeexterneabbildung", ["en"]="useexternalfigure", - ["fr"]="utilisefigureexterne", + ["fr"]="utiliserfigureexterne", ["it"]="usafiguraesterna", ["nl"]="gebruikexternfiguur", ["pe"]="استفاده‌شکل‌خارجی", @@ -6304,7 +6326,7 @@ return { ["cs"]="uzijexternisoubor", ["de"]="verwendeexternedatei", ["en"]="useexternalfile", - ["fr"]="utilisefichierexterne", + ["fr"]="utiliserfichierexterne", ["it"]="usafileesterno", ["nl"]="gebruikexternefile", ["pe"]="استفاده‌پرونده‌خارجی", @@ -6314,7 +6336,7 @@ return { ["cs"]="uzijexternisoubory", ["de"]="verwendeexternedateien", ["en"]="useexternalfiles", - ["fr"]="utilisefichiersexternes", + ["fr"]="utiliserfichiersexternes", ["it"]="usafileesterni", ["nl"]="gebruikexternefiles", ["pe"]="استفاده‌پرونده‌های‌خارجی", @@ -6324,7 +6346,7 @@ return { ["cs"]="uzijexternizvuk", ["de"]="verwendeexternestonstueck", ["en"]="useexternalsoundtrack", - ["fr"]="utilisepsiteaudioexterne", + ["fr"]="utilisersonexterne", ["it"]="usacolonnasonoraesterna", ["nl"]="gebruikexterngeluidsfragment", ["pe"]="استفاده‌قطعه‌موزیک‌خارجی", @@ -6334,7 +6356,7 @@ return { ["cs"]="uzijmodul", ["de"]="verwendemodul", ["en"]="usemodule", - ["fr"]="utilisemodule", + ["fr"]="utilisermodule", ["it"]="usamodulo", ["nl"]="gebruikmodule", ["pe"]="استفاده‌مدول", @@ -6344,7 +6366,7 @@ return { ["cs"]="uzijmoduly", ["de"]="verwendemodule", ["en"]="usemodules", - ["fr"]="utilisemodules", + ["fr"]="utilisermodules", ["it"]="usamoduli", ["nl"]="gebruikmodules", ["pe"]="استفاده‌مدولها", @@ -6354,7 +6376,7 @@ return { ["cs"]="uzijadresar", ["de"]="benutzeverzeichnis", ["en"]="usedirectory", - ["fr"]="utilisechemin", + ["fr"]="utiliserchemin", ["it"]="usacartella", ["nl"]="gebruikpad", ["pe"]="استفاده‌مسیر", @@ -6364,7 +6386,7 @@ return { ["cs"]="uzijodkazy", ["de"]="verwendereferenzen", ["en"]="usereferences", - ["fr"]="utilisereferences", + ["fr"]="utiliserreferences", ["it"]="usariferimenti", ["nl"]="gebruikreferenties", ["pe"]="استفاده‌مرجعها", @@ -6374,7 +6396,7 @@ return { ["cs"]="uzijspeciality", ["de"]="benutzespezielles", ["en"]="usespecials", - ["fr"]="utilisespecialites", + ["fr"]="utiliserspeciaux", ["it"]="usaspecialita", ["nl"]="gebruikspecials", ["pe"]="استفاده‌ویژگیها", @@ -6384,7 +6406,7 @@ return { ["cs"]="uzijsymbol", ["de"]="verwendesymbole", ["en"]="usesymbols", - ["fr"]="utilisesymboles", + ["fr"]="utilisersymboles", ["it"]="usasimboli", ["nl"]="gebruiksymbolen", ["pe"]="استفاده‌نمادها", @@ -6394,7 +6416,7 @@ return { ["cs"]="usetypescript", ["de"]="usetypescript", ["en"]="usetypescript", - ["fr"]="usetypescript", + ["fr"]="utiliserscriptdepolices", ["it"]="usetypescript", ["nl"]="gebruiktypescript", ["pe"]="استفاده‌دستخط‌تایپ", @@ -6404,6 +6426,7 @@ return { ["cs"]="usetypescriptfile", ["de"]="usetypescriptfile", ["en"]="usetypescriptfile", + ["fr"]="utiliserfichierscriptdepolices", ["it"]="usetypescriptfile", ["nl"]="gebruiktypescriptfile", ["pe"]="استفاده‌پرونده‌دستخط‌تایپ", @@ -6413,7 +6436,7 @@ return { ["cs"]="uzijurl", ["de"]="verwendeurl", ["en"]="useurl", - ["fr"]="utiliseurl", + ["fr"]="utiliserurl", ["it"]="usaurl", ["nl"]="gebruikurl", ["pe"]="useurl", @@ -6433,7 +6456,7 @@ return { ["cs"]="vl", ["de"]="vl", ["en"]="vl", - ["fr"]="vl", + ["fr"]="lv", ["it"]="vl", ["nl"]="vl", ["pe"]="خ‌ع", @@ -6463,7 +6486,7 @@ return { ["cs"]="slovovpravo", ["de"]="wortrechts", ["en"]="wordright", - ["fr"]="motdroit", + ["fr"]="ecrireadroite", ["it"]="paroladestra", ["nl"]="woordrechts", ["pe"]="کلمه‌راست", @@ -6473,7 +6496,7 @@ return { ["cs"]="zapismeziseznam", ["de"]="schreibezwischenliste", ["en"]="writebetweenlist", - ["fr"]="ecritentreliste", + ["fr"]="ecrireentreliste", ["it"]="scrividentroelenco", ["nl"]="schrijftussenlijst", ["pe"]="بنویس‌بین‌لیست", @@ -6483,7 +6506,7 @@ return { ["cs"]="zapisdoseznamu", ["de"]="schreibezurliste", ["en"]="writetolist", - ["fr"]="ecritdansliste", + ["fr"]="ecriredansliste", ["it"]="scriviinelenco", ["nl"]="schrijfnaarlijst", ["pe"]="بنویس‌در‌لیست", @@ -6493,7 +6516,7 @@ return { ["cs"]="zapisdoseznamuodkazu", ["de"]="schreibezurreferenzliste", ["en"]="writetoreferencelist", - ["fr"]="ecritdanslistereference", + ["fr"]="ecriredanslistereference", ["it"]="scriviinlistariferimenti", ["nl"]="schrijfnaarreferentielijst", ["pe"]="بنویس‌درلیست‌مرجع", @@ -6503,7 +6526,7 @@ return { ["cs"]="zapisdorejstriku", ["de"]="schreibezumregister", ["en"]="writetoregister", - ["fr"]="ecritregistre", + ["fr"]="ecriredansregistre", ["it"]="scriviinregistro", ["nl"]="schrijfnaarregister", ["pe"]="بنویس‌درثبت", @@ -6511,10 +6534,6 @@ return { }, }, ["constants"]={ - ["fractions"]={ - ["en"]="fractions", - ["nl"]="breuken", - }, ["action"]={ ["cs"]="akce", ["de"]="aktion", @@ -6539,7 +6558,7 @@ return { ["cs"]="po", ["de"]="nach", ["en"]="after", - ["fr"]="apres", + ["fr"]="après", ["it"]="dopo", ["nl"]="na", ["pe"]="بعداز", @@ -6549,7 +6568,7 @@ return { ["cs"]="pohlavicce", ["de"]="nachkopf", ["en"]="afterhead", - ["fr"]="aprestete", + ["fr"]="aprèstête", ["it"]="dopotesta", ["nl"]="kopna", ["pe"]="بعدازسر", @@ -6559,7 +6578,7 @@ return { ["cs"]="klavesapo", ["de"]="nachtaste", ["en"]="afterkey", - ["fr"]="aprescle", + ["fr"]="aprèsclé", ["it"]="dopotasto", ["nl"]="natoets", ["pe"]="بعدازکلید", @@ -6567,13 +6586,14 @@ return { }, ["aftersection"]={ ["en"]="aftersection", + ["fr"]="aprèssection", ["nl"]="nasectie", }, ["align"]={ ["cs"]="zarovnani", ["de"]="ausrichtung", ["en"]="align", - ["fr"]="alignement", + ["fr"]="aligner", ["it"]="allinea", ["nl"]="uitlijnen", ["pe"]="تنظیم", @@ -6583,42 +6603,47 @@ return { ["cs"]="aligncharacter", ["de"]="aligncharacter", ["en"]="aligncharacter", - ["fr"]="caracterealigne", + ["fr"]="alignersurcaractere", ["it"]="allineacarattere", ["nl"]="karakteruitlijnen", ["pe"]="حرف‌تنظیم", ["ro"]="aliniazacaracter", }, - ["alignmentleftwidth"]={ - ["en"]="alignmentleftwidth", - }, - ["alignmentrightwidth"]={ - ["en"]="alignmentrightwidth", - }, - ["alignmentleftsample"]={ - ["en"]="alignmentleftsample", - }, - ["alignmentrightsample"]={ - ["en"]="alignmentrightsample", - }, ["alignmentcharacter"]={ ["cs"]="alignmentcharacter", ["de"]="alignmentcharacter", ["en"]="alignmentcharacter", - ["fr"]="alignementcaractere", + ["fr"]="caracterealignement", ["it"]="carattereallineamento", ["nl"]="uitlijnkarakter", ["pe"]="حرف‌تنظیم‌کردن", ["ro"]="alierecaracter", }, + ["alignmentleftsample"]={ + ["en"]="alignmentleftsample", + ["fr"]="echantillongauchealignement", + }, + ["alignmentleftwidth"]={ + ["en"]="alignmentleftwidth", + ["fr"]="largeurgauchealignement", + }, + ["alignmentrightsample"]={ + ["en"]="alignmentrightsample", + ["fr"]="echantillondroitealignement", + }, + ["alignmentrightwidth"]={ + ["en"]="alignmentrightwidth", + ["fr"]="largeurdroitealignement", + }, ["alignsymbol"]={ ["en"]="alignsymbol", + ["fr"]="alignersursymbol", }, ["aligntitle"]={ ["cs"]="zarovnejtitul", ["de"]="titelausrichten", ["en"]="aligntitle", - ["fr"]="alignementtitre", + ["fr"]="alignersurtitre", ["it"]="allineatitolo", ["nl"]="titeluitlijnen", ["pe"]="عنوان‌تنظیم", @@ -6628,22 +6653,25 @@ return { ["cs"]="alternativa", ["de"]="alternative", ["en"]="alternative", - ["fr"]="alternative", + ["fr"]="variante", ["it"]="alternativa", ["nl"]="variant", ["pe"]="جایگزین", ["ro"]="alternativ", }, - ["stylealternative"]={ - ["en"]="stylealternative", - ["nl"]="stylevariant", - }, ["anchor"]={ ["en"]="anchor", + ["fr"]="ancre", ["nl"]="anker", }, + ["anchoring"]={ + ["en"]="anchoring", + ["fr"]="ancrage", + ["nl"]="verankering", + }, ["andtext"]={ ["en"]="andtext", + ["fr"]="ettexte", }, ["apa"]={ ["cs"]="apa", @@ -6657,6 +6685,7 @@ return { }, ["arguments"]={ ["en"]="arguments", + ["fr"]="arguments", ["nl"]="argumenten", }, ["arrow"]={ @@ -6671,24 +6700,29 @@ return { }, ["artauthor"]={ ["en"]="artauthor", + ["fr"]="artauteur", }, ["artauthoretaldisplay"]={ ["en"]="artauthoretaldisplay", + ["fr"]="artauteuretalaffichage", }, ["artauthoretallimit"]={ ["en"]="artauthoretallimit", + ["fr"]="artauteuretallimite", }, ["artauthoretaltext"]={ ["en"]="artauthoretaltext", + ["fr"]="artauteuretaltexte", }, ["artoffset"]={ ["en"]="artoffset", + ["fr"]="artdecalage", }, ["at"]={ ["cs"]="u", ["de"]="bei", ["en"]="at", - ["fr"]="a", + ["fr"]="en", ["it"]="ad", ["nl"]="op", ["pe"]="در", @@ -6706,15 +6740,19 @@ return { }, ["authorconversion"]={ ["en"]="authorconversion", + ["fr"]="auteurconversion", }, ["authoretaldisplay"]={ ["en"]="authoretaldisplay", + ["fr"]="auteuretalaffichage", }, ["authoretallimit"]={ ["en"]="authoretallimit", + ["fr"]="auteuretallimite", }, ["authoretaltext"]={ ["en"]="authoretaltext", + ["fr"]="auteuretaltexte", }, ["auto"]={ ["cs"]="auto", @@ -6728,13 +6766,14 @@ return { }, ["autocase"]={ ["en"]="autocase", + ["fr"]="autocase", ["nl"]="autocase", }, ["autofile"]={ ["cs"]="autofile", ["de"]="autofile", ["en"]="autofile", - ["fr"]="autofile", + ["fr"]="autofichier", ["it"]="autofile", ["nl"]="autofile", ["pe"]="پرونده‌خودکار", @@ -6754,7 +6793,7 @@ return { ["cs"]="autohang", ["de"]="autohang", ["en"]="autohang", - ["fr"]="autohang", + ["fr"]="autosuspendre", ["it"]="autohang", ["nl"]="autohang", ["pe"]="آویزان‌خودکار", @@ -6764,7 +6803,7 @@ return { ["cs"]="autostrut", ["de"]="autostrut", ["en"]="autostrut", - ["fr"]="autostrut", + ["fr"]="autoentretoise", ["it"]="autostrut", ["nl"]="autostrut", ["pe"]="بست‌خودکار", @@ -6782,10 +6821,12 @@ return { }, ["availableheight"]={ ["en"]="availableheight", + ["fr"]="hauteurdisponible", ["nl"]="beschikbarehoogte", }, ["availablewidth"]={ ["en"]="availablewidth", + ["fr"]="largeurdisponible", ["nl"]="beschikbarebreedte", }, ["axis"]={ @@ -6870,13 +6911,14 @@ return { }, ["backreference"]={ ["en"]="backreference", + ["fr"]="retroreference", ["nl"]="terugreferentie", }, ["backspace"]={ ["cs"]="zpetnamezera", ["de"]="rumpfspatium", ["en"]="backspace", - ["fr"]="retour", + ["fr"]="espacearrière", ["it"]="backspace", ["nl"]="rugwit", ["pe"]="فضای‌پس", @@ -6886,7 +6928,7 @@ return { ["cs"]="rovnovaha", ["de"]="ausgleichen", ["en"]="balance", - ["fr"]="equilibre", + ["fr"]="equilibrer", ["it"]="bilanciamento", ["nl"]="balanceren", ["pe"]="تعادل", @@ -6914,13 +6956,14 @@ return { }, ["beforesection"]={ ["en"]="beforesection", + ["fr"]="avantsection", ["nl"]="voorsectie", }, ["bet"]={ ["cs"]="bet", ["de"]="bet", ["en"]="bet", - ["fr"]="bet", + ["fr"]="suj", ["it"]="bet", ["nl"]="bet", ["pe"]="bet", @@ -6928,12 +6971,13 @@ return { }, ["bidi"]={ ["en"]="bidi", + ["fr"]="bidi", }, ["big"]={ ["cs"]="velky", ["de"]="gross", ["en"]="big", - ["fr"]="grand", + ["fr"]="important", ["it"]="grande", ["nl"]="groot", ["pe"]="بزرگ", @@ -6943,7 +6987,7 @@ return { ["cs"]="prazdny", ["de"]="blanko", ["en"]="blank", - ["fr"]="vide", + ["fr"]="vierge", ["it"]="rigovuoto", ["nl"]="blanko", ["pe"]="خالی", @@ -6951,12 +6995,13 @@ return { }, ["bleedoffset"]={ ["en"]="bleedoffset", + ["fr"]="decalagefuite", }, ["blockway"]={ ["cs"]="dobloku", ["de"]="blockauf", ["en"]="blockway", - ["fr"]="blockway", + ["fr"]="faconbloc", ["it"]="blockway", ["nl"]="blokwijze", ["pe"]="راه‌بلوک", @@ -6966,7 +7011,7 @@ return { ["cs"]="zakladnifont", ["de"]="fliesstext", ["en"]="bodyfont", - ["fr"]="policecorps", + ["fr"]="policedecorps", ["it"]="fonttesto", ["nl"]="korps", ["pe"]="قلم‌بدنه", @@ -6974,24 +7019,31 @@ return { }, ["boffset"]={ ["en"]="boffset", + ["fr"]="decalageb", }, ["boldfeatures"]={ ["en"]="boldfeatures", + ["fr"]="fonctionnalitesgras", }, ["boldfont"]={ ["en"]="boldfont", + ["fr"]="policegras", }, ["bolditalicfeatures"]={ ["en"]="bolditalicfeatures", + ["fr"]="fonctionnalitesgrasitalique", }, ["bolditalicfont"]={ ["en"]="bolditalicfont", + ["fr"]="policegrasitalique", }, ["boldslantedfeatures"]={ ["en"]="boldslantedfeatures", + ["fr"]="fonctionnalitesgrasincline", }, ["boldslantedfont"]={ ["en"]="boldslantedfont", + ["fr"]="policegrasincline", }, ["bookmark"]={ ["cs"]="zalozka", @@ -7007,7 +7059,7 @@ return { ["cs"]="spodek", ["de"]="unten", ["en"]="bottom", - ["fr"]="inf", + ["fr"]="bas", ["it"]="fondo", ["nl"]="onder", ["pe"]="پایین", @@ -7015,19 +7067,22 @@ return { }, ["bottomafter"]={ ["en"]="bottomafter", + ["fr"]="basaprès", }, ["bottombefore"]={ ["en"]="bottombefore", + ["fr"]="basavant", }, ["bottomcommand"]={ ["en"]="bottomcommand", + ["fr"]="commandebas", ["nl"]="ondercommando", }, ["bottomdistance"]={ ["cs"]="vzdalenostspodku", ["de"]="abstandunten", ["en"]="bottomdistance", - ["fr"]="distanceinf", + ["fr"]="distancebas", ["it"]="distanzafondo", ["nl"]="onderafstand", ["pe"]="فاصله‌پایین", @@ -7037,7 +7092,7 @@ return { ["cs"]="ramecekdole", ["de"]="untenrahmen", ["en"]="bottomframe", - ["fr"]="cadreinf", + ["fr"]="cadrebas", ["it"]="cornicefondo", ["nl"]="onderkader", ["pe"]="قالب‌پایین", @@ -7047,7 +7102,7 @@ return { ["cs"]="offsetspodku", ["de"]="untenoffset", ["en"]="bottomoffset", - ["fr"]="decalageinf", + ["fr"]="decalagebas", ["it"]="offsetfondo", ["nl"]="onderoffset", ["pe"]="آفست‌پایین", @@ -7057,7 +7112,7 @@ return { ["cs"]="bottomspace", ["de"]="bottomspace", ["en"]="bottomspace", - ["fr"]="espaceinf", + ["fr"]="espacebas", ["it"]="spaziofondo", ["nl"]="bodemwit", ["pe"]="فضای‌پایین", @@ -7067,7 +7122,7 @@ return { ["cs"]="statusspodku", ["de"]="untenstatus", ["en"]="bottomstate", - ["fr"]="etatinf", + ["fr"]="etatbas", ["it"]="statofondo", ["nl"]="onderstatus", ["pe"]="وضعیت‌پایین", @@ -7075,17 +7130,19 @@ return { }, ["break"]={ ["en"]="break", + ["fr"]="saut", ["nl"]="break", }, ["buffer"]={ ["en"]="buffer", + ["fr"]="tampon", ["nl"]="buffer", }, ["cache"]={ ["cs"]="cache", ["de"]="cache", ["en"]="cache", - ["fr"]="cache", + ["fr"]="memoirecache", ["it"]="cache", ["nl"]="cache", ["pe"]="میانگیر", @@ -7103,13 +7160,14 @@ return { }, ["category"]={ ["en"]="category", + ["fr"]="categorie", ["nl"]="categorie", }, ["ccommand"]={ ["cs"]="cprikaz", ["de"]="cbefehl", ["en"]="ccommand", - ["fr"]="ccommande", + ["fr"]="commandec", ["it"]="ccomando", ["nl"]="ccommando", ["pe"]="فرمان", @@ -7117,12 +7175,15 @@ return { }, ["character"]={ ["en"]="character", + ["fr"]="caractere", }, ["characters"]={ ["en"]="characters", + ["fr"]="caracteres", }, ["check"]={ ["en"]="check", + ["fr"]="verifier", }, ["click"]={ ["cs"]="klik", @@ -7158,7 +7219,7 @@ return { ["cs"]="clipoffset", ["de"]="clipoffset", ["en"]="clipoffset", - ["fr"]="clipoffset", + ["fr"]="decalagedecoupe", ["it"]="clipoffset", ["nl"]="clipoffset", ["pe"]="آفست‌کلیپ", @@ -7168,7 +7229,7 @@ return { ["cs"]="zavriakci", ["de"]="schliessenaktion", ["en"]="closeaction", - ["fr"]="actionfermeture", + ["fr"]="fermeraction", ["it"]="azionechiudi", ["nl"]="sluitactie", ["pe"]="بستن‌کنش", @@ -7178,7 +7239,7 @@ return { ["cs"]="closecommand", ["de"]="closecommand", ["en"]="closecommand", - ["fr"]="closecommand", + ["fr"]="fermercommande", ["it"]="closecommand", ["nl"]="sluitcommando", ["pe"]="بستن‌فرمان", @@ -7186,13 +7247,14 @@ return { }, ["closepage"]={ ["en"]="closepage", + ["fr"]="fermerpage", ["nl"]="sluitpagina", }, ["closepageaction"]={ ["cs"]="akcezavrenistranky", ["de"]="closepageaction", ["en"]="closepageaction", - ["fr"]="actionfermeturepage", + ["fr"]="fermeractionpage", ["it"]="azionechiudipagina", ["nl"]="sluitpaginaactie", ["pe"]="بستن‌عمل‌صفحه", @@ -7202,7 +7264,7 @@ return { ["cs"]="closesymbol", ["de"]="closesymbol", ["en"]="closesymbol", - ["fr"]="closesymbol", + ["fr"]="fermersymbol", ["it"]="closesymbol", ["nl"]="sluitsymbool", ["pe"]="بستن‌نماد", @@ -7250,6 +7312,7 @@ return { }, ["comma"]={ ["en"]="comma", + ["fr"]="virgule", }, ["command"]={ ["cs"]="prikaz", @@ -7265,7 +7328,7 @@ return { ["cs"]="prikazpo", ["de"]="zumbefehl", ["en"]="commandafter", - ["fr"]="commandeapres", + ["fr"]="commandeaprès", ["it"]="comdandodopo", ["nl"]="nacommando", ["pe"]="فرمان‌بعداز", @@ -7293,15 +7356,19 @@ return { }, ["comment"]={ ["en"]="comment", + ["fr"]="commentaire", }, ["commentchar"]={ ["en"]="commentchar", + ["fr"]="caracommentaire", }, ["commentoffset"]={ ["en"]="commentoffset", + ["fr"]="decalagecommentaire", }, ["compact"]={ ["en"]="compact", + ["fr"]="compact", ["nl"]="compact", }, ["component"]={ @@ -7318,7 +7385,7 @@ return { ["cs"]="compoundhyphen", ["de"]="compoundhyphen", ["en"]="compoundhyphen", - ["fr"]="compoundhyphen", + ["fr"]="traitdunioncompose", ["it"]="compoundhyphen", ["nl"]="koppelteken", ["pe"]="compoundhyphen", @@ -7328,36 +7395,42 @@ return { ["cs"]="compress", ["de"]="compress", ["en"]="compress", - ["fr"]="compress", + ["fr"]="reduire", ["it"]="compress", ["nl"]="comprimeren", ["pe"]="فشردن", ["ro"]="compress", }, - ["compressseparator"]={ - ["en"]="compressseparator", - }, ["compressdistance"]={ ["en"]="compressdistance", + ["fr"]="distancereduction", }, ["compressmethod"]={ ["en"]="compressmethod", + ["fr"]="methodereduction", + }, + ["compressseparator"]={ + ["en"]="compressseparator", + ["fr"]="separateurreduction", }, ["compressstopper"]={ ["en"]="compressstopper", + ["fr"]="stoppeurreduction", }, ["concerns"]={ ["en"]="concerns", + ["fr"]="concerne", ["nl"]="betreft", }, ["connector"]={ ["en"]="connector", + ["fr"]="connecteur", }, ["continue"]={ ["cs"]="pokracovat", ["de"]="fortsetzen", ["en"]="continue", - ["fr"]="continue", + ["fr"]="continuer", ["it"]="continua", ["nl"]="doorgaan", ["pe"]="ادامه", @@ -7367,7 +7440,7 @@ return { ["cs"]="kontrastnibarva", ["de"]="kontrastfarbe", ["en"]="contrastcolor", - ["fr"]="coleurcontraste", + ["fr"]="couleurconstrast", ["it"]="colorecontrasto", ["nl"]="contrastkleur", ["pe"]="contrastcolor", @@ -7397,7 +7470,7 @@ return { ["cs"]="konverzesouboru", ["de"]="konvertieredatei", ["en"]="convertfile", - ["fr"]="conversionfichier", + ["fr"]="convertirfichier", ["it"]="convertifile", ["nl"]="converteerfile", ["pe"]="پرونده‌تبدیل", @@ -7405,6 +7478,7 @@ return { }, ["copies"]={ ["en"]="copies", + ["fr"]="copies", ["nl"]="kopieen", }, ["corner"]={ @@ -7431,7 +7505,7 @@ return { ["cs"]="zpusobpropojeni", ["de"]="verkopplungsart", ["en"]="couplingway", - ["fr"]="modecouplage", + ["fr"]="faconcouplage", ["it"]="modoaccoppiamento", ["nl"]="koppelwijze", ["pe"]="روش‌تزویج", @@ -7447,14 +7521,17 @@ return { ["pe"]="criterium", ["ro"]="criteriu", }, - ["crossreference"]={ - ["en"]="crossreference", - }, ["cropoffset"]={ ["en"]="cropoffset", + ["fr"]="decalagerecadre", + }, + ["crossreference"]={ + ["en"]="crossreference", + ["fr"]="renvoi", }, ["cssfile"]={ ["en"]="cssfile", + ["fr"]="fichiercss", }, ["current"]={ ["cs"]="aktualni", @@ -7470,7 +7547,7 @@ return { ["cs"]="cutspace", ["de"]="cutspace", ["en"]="cutspace", - ["fr"]="cutspace", + ["fr"]="espacecoupe", ["it"]="cutspace", ["nl"]="snijwit", ["pe"]="فضای‌برش", @@ -7498,9 +7575,11 @@ return { }, ["database"]={ ["en"]="database", + ["fr"]="basededonnees", }, ["dataset"]={ ["en"]="dataset", + ["fr"]="jeudedonnees", }, ["date"]={ ["cs"]="datum", @@ -7512,15 +7591,11 @@ return { ["pe"]="تاریخ", ["ro"]="data", }, - ["time"]={ - ["en"]="time", - ["nl"]="tijd", - }, ["deepnumbercommand"]={ ["cs"]="deepnumbercommand", ["de"]="deepnumbercommand", ["en"]="deepnumbercommand", - ["fr"]="deepnumbercommand", + ["fr"]="commandeprofondenumero", ["it"]="deepnumbercommand", ["nl"]="diepnummercommando", ["pe"]="فرمان‌شماره‌عمیق", @@ -7530,7 +7605,7 @@ return { ["cs"]="deeptextcommand", ["de"]="deeptextcommand", ["en"]="deeptextcommand", - ["fr"]="deeptextcommand", + ["fr"]="commandeprofondetexte", ["it"]="deeptextcommand", ["nl"]="dieptekstcommando", ["pe"]="فرمان‌متن‌عمیق", @@ -7550,7 +7625,7 @@ return { ["cs"]="prodleva", ["de"]="wartezeit", ["en"]="delay", - ["fr"]="delai", + ["fr"]="retard", ["it"]="attesa", ["nl"]="wachttijd", ["pe"]="تاخیر", @@ -7606,6 +7681,10 @@ return { ["pe"]="نمایش", ["ro"]="display", }, + ["displaythreshold"]={ + ["en"]="displaythreshold", + ["fr"]="seuilaffichage", + }, ["distance"]={ ["cs"]="vzdalenost", ["de"]="abstand", @@ -7618,6 +7697,7 @@ return { }, ["domain"]={ ["en"]="domain", + ["fr"]="domaine", }, ["dot"]={ ["cs"]="tecka", @@ -7641,12 +7721,13 @@ return { }, ["down"]={ ["en"]="down", + ["fr"]="enbas", }, ["dummy"]={ ["cs"]="dummy", ["de"]="dummy", ["en"]="dummy", - ["fr"]="dummy", + ["fr"]="factice", ["it"]="dummy", ["nl"]="dummy", ["pe"]="مصنوعی", @@ -7694,15 +7775,19 @@ return { }, ["editor"]={ ["en"]="editor", + ["fr"]="editeur", }, ["editoretaldisplay"]={ ["en"]="editoretaldisplay", + ["fr"]="editeurealaffichage", }, ["editoretallimit"]={ ["en"]="editoretallimit", + ["fr"]="editeureallimite", }, ["editoretaltext"]={ ["en"]="editoretaltext", + ["fr"]="editeurealtexte", }, ["empty"]={ ["cs"]="prazdne", @@ -7716,17 +7801,19 @@ return { }, ["entities"]={ ["en"]="entities", + ["fr"]="entitees", ["nl"]="entities", }, ["entries"]={ ["en"]="entries", + ["fr"]="entrees", ["nl"]="ingangen", }, ["equalheight"]={ ["cs"]="equalheight", ["de"]="equalheight", ["en"]="equalheight", - ["fr"]="equalheight", + ["fr"]="hauteuregale", ["it"]="equalheight", ["nl"]="equalheight", ["pe"]="ارتفاع‌یکسان", @@ -7736,7 +7823,7 @@ return { ["cs"]="equalwidth", ["de"]="equalwidth", ["en"]="equalwidth", - ["fr"]="equalwidth", + ["fr"]="margeuregale", ["it"]="equalwidth", ["nl"]="equalwidth", ["pe"]="عرض‌یکسان", @@ -7746,7 +7833,7 @@ return { ["cs"]="escape", ["de"]="escape", ["en"]="escape", - ["fr"]="escape", + ["fr"]="echappatoire", ["it"]="escape", ["nl"]="escape", ["pe"]="فرار", @@ -7754,15 +7841,19 @@ return { }, ["etaldisplay"]={ ["en"]="etaldisplay", + ["fr"]="etalaffichage", }, ["etallimit"]={ ["en"]="etallimit", + ["fr"]="etallimite", }, ["etaloption"]={ ["en"]="etaloption", + ["fr"]="etaloption", }, ["etaltext"]={ ["en"]="etaltext", + ["fr"]="etalttexte", }, ["evenmargin"]={ ["cs"]="sudamarginalie", @@ -7776,9 +7867,11 @@ return { }, ["exact"]={ ["en"]="exact", + ["fr"]="exact", }, ["exitoffset"]={ ["en"]="exitoffset", + ["fr"]="decalagesortie", }, ["expansion"]={ ["cs"]="expanzen", @@ -7792,6 +7885,7 @@ return { }, ["export"]={ ["en"]="export", + ["fr"]="exporter", ["nl"]="exporteer", }, ["extras"]={ @@ -7818,7 +7912,7 @@ return { ["cs"]="fallback", ["de"]="fallback", ["en"]="fallback", - ["fr"]="fallback", + ["fr"]="repli", ["it"]="fallback", ["nl"]="terugval", ["pe"]="عقب‌ریختن", @@ -7836,12 +7930,15 @@ return { }, ["features"]={ ["en"]="features", + ["fr"]="fonctionnalites", }, ["fences"]={ ["en"]="fences", + ["fr"]="barrieres", }, ["field"]={ ["en"]="field", + ["fr"]="champ", ["nl"]="veld", }, ["fieldbackgroundcolor"]={ @@ -7878,7 +7975,7 @@ return { ["cs"]="offsetpole", ["de"]="feldoffset", ["en"]="fieldoffset", - ["fr"]="offsetchamp", + ["fr"]="decalagechamp", ["it"]="offsetcampo", ["nl"]="veldoffset", ["pe"]="آفست‌میدان", @@ -7896,21 +7993,27 @@ return { }, ["filler"]={ ["en"]="filler", + ["fr"]="remplisseur", }, ["filter"]={ ["en"]="filter", + ["fr"]="filtre", }, ["filtercommand"]={ ["en"]="filtercommand", + ["fr"]="commandefiltre", }, ["finalnamesep"]={ ["en"]="finalnamesep", + ["fr"]="sepnomfinal", }, ["finalpagesep"]={ ["en"]="finalpagesep", + ["fr"]="seppagefinale", }, ["finalpubsep"]={ ["en"]="finalpubsep", + ["fr"]="seppubfinale", }, ["first"]={ ["cs"]="prvni", @@ -7924,6 +8027,7 @@ return { }, ["firstnamesep"]={ ["en"]="firstnamesep", + ["fr"]="seppremiernom", }, ["firstpage"]={ ["cs"]="prvnistranka", @@ -7955,6 +8059,11 @@ return { ["pe"]="تمرکزدرون", ["ro"]="focusin", }, + ["focusoffset"]={ + ["en"]="focusoffset", + ["fr"]="decalagefocus", + ["nl"]="focusoffset", + }, ["focusout"]={ ["cs"]="focusout", ["de"]="focusout", @@ -7965,10 +8074,6 @@ return { ["pe"]="تمرکزبیرون", ["ro"]="focusout", }, - ["focusoffset"]={ - ["en"]="focusoffset", - ["nl"]="focusoffset", - }, ["footer"]={ ["cs"]="upati", ["de"]="fusszeile", @@ -7983,7 +8088,7 @@ return { ["cs"]="vzdalenostupati", ["de"]="fusszeilenabstand", ["en"]="footerdistance", - ["fr"]="dsitancepdp", + ["fr"]="distancepdp", ["it"]="distanzapdp", ["nl"]="voetafstand", ["pe"]="فاصله‌ته‌برگ", @@ -8003,7 +8108,7 @@ return { ["cs"]="sila", ["de"]="zwinge", ["en"]="force", - ["fr"]="force", + ["fr"]="forcer", ["it"]="forza", ["nl"]="forceer", ["pe"]="اجبار", @@ -8039,6 +8144,11 @@ return { ["pe"]="شمایل", ["ro"]="format", }, + ["fractions"]={ + ["en"]="fractions", + ["fr"]="fractions", + ["nl"]="breuken", + }, ["frame"]={ ["cs"]="ramecek", ["de"]="rahmen", @@ -8111,6 +8221,7 @@ return { }, ["freeregion"]={ ["en"]="freeregion", + ["fr"]="regionlibre", ["nl"]="vrijgebied", }, ["from"]={ @@ -8125,15 +8236,17 @@ return { }, ["functioncolor"]={ ["en"]="functioncolor", + ["fr"]="couleurfonction", }, ["functionstyle"]={ ["en"]="functionstyle", + ["fr"]="stylefonction", }, ["get"]={ ["cs"]="ziskat", ["de"]="hole", ["en"]="get", - ["fr"]="obtient", + ["fr"]="obtenir", ["it"]="prendi", ["nl"]="haal", ["pe"]="بگیر", @@ -8151,6 +8264,7 @@ return { }, ["goodies"]={ ["en"]="goodies", + ["fr"]="friandises", }, ["grid"]={ ["cs"]="mrizka", @@ -8164,15 +8278,17 @@ return { }, ["group"]={ ["en"]="group", + ["fr"]="groupe", }, ["groupsuffix"]={ ["en"]="groupsuffix", + ["fr"]="suffixegroupe", }, ["hang"]={ ["cs"]="zaveseni", ["de"]="haengend", ["en"]="hang", - ["fr"]="suspend", + ["fr"]="suspendre", ["it"]="sospendi", ["nl"]="hang", ["pe"]="بیاویز", @@ -8180,10 +8296,12 @@ return { }, ["hcompact"]={ ["en"]="hcompact", + ["fr"]="compacth", ["nl"]="hcomprimeer", }, ["headalign"]={ ["en"]="headalign", + ["fr"]="alignertete", ["nl"]="kopuitlijnen", }, ["headcolor"]={ @@ -8216,15 +8334,11 @@ return { ["pe"]="تبدیل‌سر", ["ro"]="conversietitlu", }, - ["headseparator"]={ - ["en"]="headseparator", - ["nl"]="kopscheider", - }, ["header"]={ ["cs"]="zahlavi", ["de"]="kopfzeile", ["en"]="header", - ["fr"]="entete", + ["fr"]="entête", ["it"]="intestazione", ["nl"]="hoofd", ["pe"]="سربرگ", @@ -8234,7 +8348,7 @@ return { ["cs"]="vzdalenostzahlavi", ["de"]="kopfzeilenabstand", ["en"]="headerdistance", - ["fr"]="distanceentete", + ["fr"]="distanceentête", ["it"]="distanzaintestazione", ["nl"]="hoofdafstand", ["pe"]="فاصله‌سربرگ", @@ -8244,7 +8358,7 @@ return { ["cs"]="statuszahlavi", ["de"]="kopfzeilenstatus", ["en"]="headerstate", - ["fr"]="etatentete", + ["fr"]="etatentête", ["it"]="statointestazione", ["nl"]="hoofdstatus", ["pe"]="وضعیت‌سربرگ", @@ -8270,6 +8384,11 @@ return { ["pe"]="شماره‌سر", ["ro"]="numartitlu", }, + ["headseparator"]={ + ["en"]="headseparator", + ["fr"]="separateurtete", + ["nl"]="kopscheider", + }, ["headstyle"]={ ["cs"]="stylhlavicky", ["de"]="kopfstil", @@ -8294,25 +8413,17 @@ return { ["cs"]="hfaktor", ["de"]="hfaktor", ["en"]="hfactor", - ["fr"]="facteurhauteur", + ["fr"]="facteurh", ["it"]="hfactor", ["nl"]="hfactor", ["pe"]="عامل‌ارتفاع", ["ro"]="hfactor", }, - ["vfactor"]={ - ["cs"]="vfaktor", - ["de"]="vfaktor", - ["en"]="vfactor", - ["it"]="vfactor", - ["nl"]="vfactor", - ["ro"]="vfactor", - }, ["hfil"]={ ["cs"]="hfil", ["de"]="hfil", ["en"]="hfil", - ["fr"]="hfil", + ["fr"]="remplissageh", ["it"]="hfil", ["nl"]="hfil", ["pe"]="پرکردن‌ارتفاع", @@ -8320,32 +8431,33 @@ return { }, ["hidenumber"]={ ["en"]="hidenumber", - }, - ["horizontal"]={ - ["cs"]="horizontalne", - ["de"]="horizontal", - ["en"]="horizontal", - ["fr"]="horizontale", - ["it"]="orizzontale", - ["nl"]="horizontaal", - ["pe"]="افقی", - ["ro"]="orizontal", + ["fr"]="cachernumero", }, ["hoffset"]={ ["cs"]="hoffset", ["de"]="hoffset", ["en"]="hoffset", - ["fr"]="decalagehauteur", + ["fr"]="decalageh", ["it"]="hoffset", ["nl"]="hoffset", ["pe"]="آفست‌ا", ["ro"]="hoffset", }, + ["horizontal"]={ + ["cs"]="horizontalne", + ["de"]="horizontal", + ["en"]="horizontal", + ["fr"]="horizontal", + ["it"]="orizzontale", + ["nl"]="horizontaal", + ["pe"]="افقی", + ["ro"]="orizontal", + }, ["horoffset"]={ ["cs"]="horoffset", ["de"]="rumpfabstand", ["en"]="horoffset", - ["fr"]="horoffset", + ["fr"]="decalagehor", ["it"]="horoffset", ["nl"]="rugoffset", ["pe"]="آفست‌افق", @@ -8355,7 +8467,7 @@ return { ["cs"]="hyphen", ["de"]="hyphen", ["en"]="hyphen", - ["fr"]="hyphen", + ["fr"]="traitdunion", ["it"]="hyphen", ["nl"]="hyphen", ["pe"]="شکستن", @@ -8363,12 +8475,13 @@ return { }, ["hyphens"]={ ["en"]="hyphens", + ["fr"]="traitsdunion", }, ["icommand"]={ ["cs"]="iprikaz", ["de"]="ibefehl", ["en"]="icommand", - ["fr"]="icommande", + ["fr"]="commandei", ["it"]="icomando", ["nl"]="icommando", ["pe"]="icommand", @@ -8376,12 +8489,13 @@ return { }, ["ignore"]={ ["en"]="ignore", + ["fr"]="ignorer", }, ["in"]={ ["cs"]="v", ["de"]="in", ["en"]="in", - ["fr"]="in", + ["fr"]="dans", ["it"]="in", ["nl"]="in", ["pe"]="درون", @@ -8401,7 +8515,7 @@ return { ["cs"]="zvysit", ["de"]="erhoehen", ["en"]="increment", - ["fr"]="incremente", + ["fr"]="incrementer", ["it"]="incremento", ["nl"]="verhoog", ["pe"]="افزایش", @@ -8411,7 +8525,7 @@ return { ["cs"]="zvysujicicislo", ["de"]="nummererhoehen", ["en"]="incrementnumber", - ["fr"]="incrementenumero", + ["fr"]="incrementernumero", ["it"]="incrementanumero", ["nl"]="verhoognummer", ["pe"]="شماره‌افزایش", @@ -8421,7 +8535,7 @@ return { ["cs"]="odsazovani", ["de"]="einziehen", ["en"]="indenting", - ["fr"]="composeenalinea", + ["fr"]="indentation", ["it"]="rientro", ["nl"]="inspringen", ["pe"]="تورفتگی", @@ -8431,7 +8545,7 @@ return { ["cs"]="odsadpristi", ["de"]="ziehefolgendeein", ["en"]="indentnext", - ["fr"]="indentesuivant", + ["fr"]="indenterauuivant", ["it"]="rientrasuccessivo", ["nl"]="springvolgendein", ["pe"]="متن‌تورفته", @@ -8439,6 +8553,7 @@ return { }, ["index"]={ ["en"]="index", + ["fr"]="index", }, ["indicator"]={ ["cs"]="indikator", @@ -8452,6 +8567,11 @@ return { }, ["initialsep"]={ ["en"]="initialsep", + ["fr"]="sepinitial", + }, + ["inlinethreshold"]={ + ["en"]="inlinethreshold", + ["fr"]="seuilenligne", }, ["inner"]={ ["cs"]="vnitrni", @@ -8485,13 +8605,16 @@ return { }, ["insidesection"]={ ["en"]="insidesection", + ["fr"]="auseinsection", ["nl"]="binnensectie", }, ["instance"]={ ["en"]="instance", + ["fr"]="instance", }, ["intent"]={ ["en"]="intent", + ["fr"]="intention", }, ["interaction"]={ ["cs"]="interakce", @@ -8515,19 +8638,22 @@ return { }, ["internalgrid"]={ ["en"]="internalgrid", + ["fr"]="grilleinterieure", ["nl"]="interngrid", }, ["italicfeatures"]={ ["en"]="italicfeatures", + ["fr"]="fonctionnalitesitalique", }, ["italicfont"]={ ["en"]="italicfont", + ["fr"]="policeitalique", }, ["itemalign"]={ ["cs"]="itemalign", ["de"]="itemalign", ["en"]="itemalign", - ["fr"]="itemalign", + ["fr"]="alignerelem", ["it"]="itemalign", ["nl"]="itemuitlijnen", ["pe"]="تنظیم‌آیتم", @@ -8537,7 +8663,7 @@ return { ["cs"]="polozky", ["de"]="posten", ["en"]="items", - ["fr"]="elements", + ["fr"]="élément", ["it"]="elementi", ["nl"]="items", ["pe"]="آیتمها", @@ -8545,21 +8671,25 @@ return { }, ["joiners"]={ ["en"]="joiners", + ["fr"]="joins", }, ["journalconversion"]={ ["en"]="journalconversion", + ["fr"]="conversionjournal", }, ["juniorsep"]={ ["en"]="juniorsep", + ["fr"]="sepjunior", }, ["keeptogether"]={ ["en"]="keeptogether", + ["fr"]="conserverensemble", }, ["ken"]={ ["cs"]="ken", ["de"]="ken", ["en"]="ken", - ["fr"]="ken", + ["fr"]="rep", ["it"]="ken", ["nl"]="ken", ["pe"]="ken", @@ -8569,7 +8699,7 @@ return { ["cs"]="keyexpansion", ["de"]="keyexpansion", ["en"]="keyexpansion", - ["fr"]="keyexpansion", + ["fr"]="expansioncle", ["it"]="keyexpansion", ["nl"]="sleutelexpansie", ["pe"]="گسترش‌کلید", @@ -8577,13 +8707,14 @@ return { }, ["keys"]={ ["en"]="keys", + ["fr"]="cles", ["nl"]="sleutels", }, ["keyword"]={ ["cs"]="keyword", ["de"]="keyword", ["en"]="keyword", - ["fr"]="motcle", + ["fr"]="motclé", ["it"]="parolachiave", ["nl"]="trefwoord", ["pe"]="کلید‌واژه", @@ -8599,29 +8730,36 @@ return { ["pe"]="برچسب", ["ro"]="eticheta", }, + ["labelalternative"]={ + ["en"]="labelalternative", + ["fr"]="varianteetiquette", + ["nl"]="labelvariant", + }, + ["labelcolor"]={ + ["en"]="labelcolor", + ["fr"]="couleuretiquette", + ["nl"]="labelkleur", + }, ["labeloffset"]={ ["en"]="labeloffset", - }, - ["labelalternative"]={ - ["en"]="labelalternative", - ["nl"]="labelvariant", + ["fr"]="decalageetiquette", }, ["labelstyle"]={ - ["en"]="labelstyle", - ["nl"]="labelletter", - }, - ["labelcolor"]={ - ["en"]="labelcolor", - ["nl"]="labelkleur", + ["en"]="labelstyle", + ["fr"]="styleetiquette", + ["nl"]="labelletter", }, ["language"]={ ["en"]="language", + ["fr"]="langue", }, ["last"]={ ["en"]="last", + ["fr"]="dernier", }, ["lastnamesep"]={ ["en"]="lastnamesep", + ["fr"]="sepderniernom", }, ["lastpage"]={ ["cs"]="poslednistrana", @@ -8635,12 +8773,15 @@ return { }, ["lastpagesep"]={ ["en"]="lastpagesep", + ["fr"]="sepdernierepage", }, ["lastpubsep"]={ ["en"]="lastpubsep", + ["fr"]="sepdernierepub", }, ["layout"]={ ["en"]="layout", + ["fr"]="miseenpage", ["nl"]="layout", }, ["left"]={ @@ -8667,7 +8808,7 @@ return { ["cs"]="leftcompoundhyphen", ["de"]="leftcompoundhyphen", ["en"]="leftcompoundhyphen", - ["fr"]="leftcompoundhyphen", + ["fr"]="traitdunioncomposegauche", ["it"]="leftcompoundhyphen", ["nl"]="linkerkoppelteken", ["pe"]="leftcompoundhyphen", @@ -8707,7 +8848,7 @@ return { ["cs"]="lefthyphen", ["de"]="lefthyphen", ["en"]="lefthyphen", - ["fr"]="lefthyphen", + ["fr"]="traitduniongauche", ["it"]="lefthyphen", ["nl"]="lefthyphen", ["pe"]="شکست‌چپ", @@ -8763,6 +8904,10 @@ return { ["pe"]="نقل‌چپ", ["ro"]="minicitatstanga", }, + ["leftsample"]={ + ["en"]="leftsample", + ["fr"]="echantillongauche", + }, ["leftsentence"]={ ["cs"]="vetavlevo", ["de"]="linkersatz", @@ -8777,7 +8922,7 @@ return { ["cs"]="leftspeech", ["de"]="leftspeech", ["en"]="leftspeech", - ["fr"]="leftspeech", + ["fr"]="discoursgauche", ["it"]="leftspeech", ["nl"]="linkeruitspraak", ["pe"]="سخنرانی‌چپ", @@ -8787,7 +8932,7 @@ return { ["cs"]="stylvlevo", ["de"]="linkerstil", ["en"]="leftstyle", - ["fr"]="leftstyle", + ["fr"]="stylegauche", ["it"]="stilesinistra", ["nl"]="linkerletter", ["pe"]="سبک‌چپ", @@ -8825,9 +8970,11 @@ return { }, ["leftwords"]={ ["en"]="leftwords", + ["fr"]="motsgauche", }, ["less"]={ ["en"]="less", + ["fr"]="moins", ["nl"]="minder", }, ["level"]={ @@ -8854,7 +9001,7 @@ return { ["cs"]="limittext", ["de"]="limittext", ["en"]="limittext", - ["fr"]="limittext", + ["fr"]="textelimite", ["it"]="limittext", ["nl"]="limiettekst", ["pe"]="مرزمتن", @@ -8932,6 +9079,7 @@ return { }, ["loffset"]={ ["en"]="loffset", + ["fr"]="decalagel", }, ["logo"]={ ["cs"]="logo", @@ -8957,7 +9105,7 @@ return { ["cs"]="barvaznacky", ["de"]="beschrfarbe", ["en"]="marcolor", - ["fr"]="couleurmarquage", + ["fr"]="couleurrem", ["it"]="coloremarcatura", ["nl"]="markleur", ["pe"]="رنگ‌حاش", @@ -8987,7 +9135,7 @@ return { ["cs"]="textovahrana", ["de"]="marginalkante", ["en"]="marginedge", - ["fr"]="bordmarge", + ["fr"]="margebord", ["it"]="bordomargine", ["nl"]="kantlijn", ["pe"]="لبه‌حاشیه", @@ -8997,7 +9145,7 @@ return { ["cs"]="textmarginalnihookraje", ["de"]="marginalkantetext", ["en"]="marginedgetext", - ["fr"]="textebordmarge", + ["fr"]="textemargebord", ["it"]="testobordomargine", ["nl"]="kantlijntekst", ["pe"]="متن‌لبه‌حاشیه", @@ -9015,6 +9163,7 @@ return { }, ["mark"]={ ["en"]="mark", + ["fr"]="marque", ["nl"]="kernmerk", }, ["marking"]={ @@ -9031,7 +9180,7 @@ return { ["cs"]="stylsnacky", ["de"]="beschrstil", ["en"]="marstyle", - ["fr"]="stylemarquage", + ["fr"]="stylerem", ["it"]="stilemarcatura", ["nl"]="marletter", ["pe"]="سبک‌حاش", @@ -9039,16 +9188,20 @@ return { }, ["mask"]={ ["en"]="mask", + ["fr"]="masque", ["nl"]="masker", }, ["mathclass"]={ ["en"]="mathclass", + ["fr"]="classemath", }, ["mathlimits"]={ ["en"]="mathlimits", + ["fr"]="limitesmath", }, ["mathstyle"]={ ["en"]="mathstyle", + ["fr"]="stylemath", }, ["max"]={ ["cs"]="max", @@ -9062,6 +9215,7 @@ return { }, ["maxdepth"]={ ["en"]="maxdepth", + ["fr"]="profondeurmax", }, ["maxheight"]={ ["cs"]="maxvyska", @@ -9085,6 +9239,7 @@ return { }, ["maybeyear"]={ ["en"]="maybeyear", + ["fr"]="anneepeutetre", }, ["menu"]={ ["cs"]="menu", @@ -9116,47 +9271,51 @@ return { ["pe"]="میان", ["ro"]="mijloc", }, - ["middlecommand"]={ - ["en"]="middlecommand", - ["nl"]="middencommando", - }, ["middlecolor"]={ ["en"]="middlecolor", + ["fr"]="couleurmilieu", ["nl"]="middenkleur", }, - ["middlestyle"]={ - ["en"]="middlestyle", - ["nl"]="middenletter", - }, - ["middlewidth"]={ - ["en"]="middlewidth", - ["nl"]="middenbreedte", + ["middlecommand"]={ + ["en"]="middlecommand", + ["fr"]="commandemilieu", + ["nl"]="middencommando", }, ["middlespeech"]={ ["cs"]="middlespeech", ["de"]="middlespeech", ["en"]="middlespeech", - ["fr"]="middlespeech", + ["fr"]="discoursmilieu", ["it"]="middlespeech", ["nl"]="middenuitspraak", ["pe"]="سخنرانی‌میانی", ["ro"]="middlespeech", }, + ["middlestyle"]={ + ["en"]="middlestyle", + ["fr"]="stylemilieu", + ["nl"]="middenletter", + }, ["middletext"]={ ["cs"]="strednitext", ["de"]="mittigertext", ["en"]="middletext", - ["fr"]="textecentre", + ["fr"]="textemilieu", ["it"]="testocentro", ["nl"]="middentekst", ["pe"]="متن‌میانی", ["ro"]="textmijloc", }, + ["middlewidth"]={ + ["en"]="middlewidth", + ["fr"]="largeurmilieu", + ["nl"]="middenbreedte", + }, ["midsentence"]={ ["cs"]="midsentence", ["de"]="midsentence", ["en"]="midsentence", - ["fr"]="midsentence", + ["fr"]="milieuphrase", ["it"]="midsentence", ["nl"]="middenzin", ["pe"]="جمله‌میانی", @@ -9206,7 +9365,7 @@ return { ["cs"]="moffset", ["de"]="moffset", ["en"]="moffset", - ["fr"]="moffset", + ["fr"]="decalagem", ["it"]="moffset", ["nl"]="moffset", ["pe"]="moffset", @@ -9214,26 +9373,32 @@ return { }, ["monthconversion"]={ ["en"]="monthconversion", + ["fr"]="conversionmois", ["nl"]="maandconversie", }, ["more"]={ ["en"]="more", + ["fr"]="plus", ["nl"]="meer", }, ["mpdepth"]={ ["en"]="mpdepth", + ["fr"]="profondeurmp", ["nl"]="mpdiepte", }, ["mpheight"]={ ["en"]="mpheight", + ["fr"]="hauteurmp", ["nl"]="mphoogte", }, ["mpoffset"]={ ["en"]="mpoffset", + ["fr"]="decalagemp", ["nl"]="mpoffset", }, ["mpwidth"]={ ["en"]="mpwidth", + ["fr"]="largeurmp", ["nl"]="mpbreedte", }, ["n"]={ @@ -9258,12 +9423,13 @@ return { }, ["namesep"]={ ["en"]="namesep", + ["fr"]="sepnom", }, ["nbottom"]={ ["cs"]="nspodek", ["de"]="nunten", ["en"]="nbottom", - ["fr"]="ninf", + ["fr"]="nbas", ["it"]="nfondo", ["nl"]="nonder", ["pe"]="nbottom", @@ -9291,15 +9457,19 @@ return { }, ["nextleft"]={ ["en"]="nextleft", + ["fr"]="suivantgauche", }, ["nextleftquotation"]={ ["en"]="nextleftquotation", + ["fr"]="citationgauchesuivante", }, ["nextright"]={ ["en"]="nextright", + ["fr"]="suivantdroite", }, ["nextrightquotation"]={ ["en"]="nextrightquotation", + ["fr"]="citationdroitesuivante", }, ["nl"]={ ["cs"]="nl", @@ -9343,10 +9513,12 @@ return { }, ["note"]={ ["en"]="note", + ["fr"]="note", ["nl"]="noot", }, ["notes"]={ ["en"]="notes", + ["fr"]="notes", ["nl"]="noten", }, ["nr"]={ @@ -9373,7 +9545,7 @@ return { ["cs"]="nvrsek", ["de"]="noben", ["en"]="ntop", - ["fr"]="nsup", + ["fr"]="nhaut", ["it"]="ncima", ["nl"]="nboven", ["pe"]="ntop", @@ -9391,6 +9563,7 @@ return { }, ["numberalign"]={ ["en"]="numberalign", + ["fr"]="alignernumero", ["nl"]="nummeruitlijnen", }, ["numbercolor"]={ @@ -9415,15 +9588,17 @@ return { }, ["numberconversion"]={ ["en"]="numberconversion", + ["fr"]="conversionnumero", }, ["numberconversionset"]={ ["en"]="numberconversionset", + ["fr"]="jeuconversionnumero", }, ["numberdistance"]={ ["cs"]="numberdistance", ["de"]="numberdistance", ["en"]="numberdistance", - ["fr"]="numberdistance", + ["fr"]="distancenumero", ["it"]="numberdistance", ["nl"]="nummerafstand", ["pe"]="فاصله‌شماره", @@ -9433,7 +9608,7 @@ return { ["cs"]="cislovani", ["de"]="nummerierung", ["en"]="numbering", - ["fr"]="numerotation", + ["fr"]="numérotation", ["it"]="numerazione", ["nl"]="nummeren", ["pe"]="شماره‌گذاری", @@ -9441,18 +9616,21 @@ return { }, ["numberorder"]={ ["en"]="numberorder", + ["fr"]="ordrenumero", }, ["numberprefix"]={ ["en"]="numberprefix", + ["fr"]="prefixenumero", }, ["numbersegments"]={ ["en"]="numbersegments", + ["fr"]="segmentsnumero", }, ["numberseparator"]={ ["cs"]="oddelovaccisla", ["de"]="nummernseperator", ["en"]="numberseparator", - ["fr"]="separateurnumbero", + ["fr"]="separateurnumero", ["it"]="separatorenumero", ["nl"]="nummerscheider", ["pe"]="جداکننده‌شماره", @@ -9460,15 +9638,24 @@ return { }, ["numberseparatorset"]={ ["en"]="numberseparatorset", + ["fr"]="jeuseparateurnumero", }, ["numberset"]={ ["en"]="numberset", + ["fr"]="jeunumero", }, ["numberstarter"]={ ["en"]="numberstarter", + ["fr"]="demarreurnumero", }, ["numberstopper"]={ ["en"]="numberstopper", + ["fr"]="stoppeurnumero", + }, + ["numberstrut"]={ + ["en"]="numberstrut", + ["fr"]="entretoisenumero", + ["nl"]="nummerstrut", }, ["numberstyle"]={ ["cs"]="stylcisla", @@ -9484,7 +9671,7 @@ return { ["cs"]="numberwidth", ["de"]="numberwidth", ["en"]="numberwidth", - ["fr"]="numberwidth", + ["fr"]="largeurnumero", ["it"]="numberwidth", ["nl"]="nummerbreedte", ["pe"]="عرض‌شماره", @@ -9534,7 +9721,7 @@ return { ["cs"]="lichyokraj", ["de"]="ungeraderand", ["en"]="oddmargin", - ["fr"]="margepaire", + ["fr"]="margeimpaire", ["it"]="marginedispari", ["nl"]="onevenmarge", ["pe"]="حاشیه‌فرد", @@ -9544,7 +9731,7 @@ return { ["cs"]="offset", ["de"]="offset", ["en"]="offset", - ["fr"]="offset", + ["fr"]="decalage", ["it"]="offset", ["nl"]="offset", ["pe"]="آفست", @@ -9554,7 +9741,7 @@ return { ["cs"]="otevriakci", ["de"]="oeffenaktion", ["en"]="openaction", - ["fr"]="actionouverture", + ["fr"]="actionouvrir", ["it"]="azioneapri", ["nl"]="openactie", ["pe"]="عمل‌باز", @@ -9562,13 +9749,14 @@ return { }, ["openpage"]={ ["en"]="openpage", + ["fr"]="ouvrirpage", ["nl"]="openpagina", }, ["openpageaction"]={ ["cs"]="akceotevrenistranky", ["de"]="openpageaction", ["en"]="openpageaction", - ["fr"]="actionouverturepage", + ["fr"]="actionouvrirpage", ["it"]="azioneapripagina", ["nl"]="openpaginaactie", ["pe"]="عمل‌صفحه‌باز", @@ -9576,9 +9764,11 @@ return { }, ["openup"]={ ["en"]="openup", + ["fr"]="ouverture", }, ["opticalsize"]={ ["en"]="opticalsize", + ["fr"]="tailleoptique", }, ["option"]={ ["cs"]="volba", @@ -9592,12 +9782,9 @@ return { }, ["order"]={ ["en"]="order", + ["fr"]="ordre", ["nl"]="volgorde", }, - ["anchoring"]={ - ["en"]="anchoring", - ["nl"]="verankering", - }, ["orientation"]={ ["cs"]="orientation", ["de"]="orientation", @@ -9610,6 +9797,7 @@ return { }, ["otherstext"]={ ["en"]="otherstext", + ["fr"]="texteautres", }, ["outermargin"]={ ["cs"]="outermargin", @@ -9625,17 +9813,21 @@ return { ["cs"]="overprint", ["de"]="overprint", ["en"]="overprint", - ["fr"]="overprint", + ["fr"]="surimpression", ["it"]="overprint", ["nl"]="overprint", ["pe"]="overprint", ["ro"]="overprint", }, + ["ownerpassword"]={ + ["en"]="ownerpassword", + ["fr"]="motdepasseproprietaire", + }, ["ownnumber"]={ ["cs"]="vlastnicislo", ["de"]="eigenenummer", ["en"]="ownnumber", - ["fr"]="numeroproprio", + ["fr"]="numeropropre", ["it"]="numeroproprio", ["nl"]="eigennummer", ["pe"]="شماره‌خود", @@ -9643,6 +9835,7 @@ return { }, ["packcriterium"]={ ["en"]="packcriterium", + ["fr"]="criterepack", ["nl"]="opelkaarcriterium", }, ["page"]={ @@ -9659,7 +9852,7 @@ return { ["cs"]="hranicestranky", ["de"]="seitenbegrenzung", ["en"]="pageboundaries", - ["fr"]="limitespage", + ["fr"]="frontierespage", ["it"]="limitipagina", ["nl"]="paginaovergangen", ["pe"]="مرزهای‌صفحه", @@ -9677,6 +9870,7 @@ return { }, ["pagecolormodel"]={ ["en"]="pagecolormodel", + ["fr"]="modelecouleurpage", ["nl"]="paginakleurmodel", }, ["pagecommand"]={ @@ -9691,18 +9885,23 @@ return { }, ["pageconnector"]={ ["en"]="pageconnector", + ["fr"]="connecteurpage", }, ["pageconversion"]={ ["en"]="pageconversion", + ["fr"]="conversionpage", }, ["pageconversionset"]={ ["en"]="pageconversionset", + ["fr"]="jeuconversionpage", }, ["pageleft"]={ ["en"]="pageleft", + ["fr"]="pagegauche", }, ["pagemethod"]={ ["en"]="pagemethod", + ["fr"]="methodepage", ["nl"]="paginamethode", }, ["pagenumber"]={ @@ -9717,48 +9916,63 @@ return { }, ["pageprefix"]={ ["en"]="pageprefix", + ["fr"]="prefixepage", }, ["pageprefixconnector"]={ ["en"]="pageprefixconnector", + ["fr"]="connecteurprefixepage", }, ["pageprefixconversion"]={ ["en"]="pageprefixconversion", + ["fr"]="conversionprefixepage", }, ["pageprefixconversionset"]={ ["en"]="pageprefixconversionset", + ["fr"]="jeuconversionprefixepage", }, ["pageprefixsegments"]={ ["en"]="pageprefixsegments", + ["fr"]="segmentsprefixepage", }, ["pageprefixseparatorset"]={ ["en"]="pageprefixseparatorset", + ["fr"]="jeuseparateurprefixepage", }, ["pageprefixset"]={ ["en"]="pageprefixset", + ["fr"]="jeuprefixepage", }, ["pageprefixstarter"]={ ["en"]="pageprefixstarter", + ["fr"]="demarreurprefixepage", }, ["pageprefixstopper"]={ ["en"]="pageprefixstopper", + ["fr"]="stoppeurprefixpage", }, ["pageright"]={ ["en"]="pageright", + ["fr"]="pagedroite", }, ["pagesegments"]={ ["en"]="pagesegments", + ["fr"]="segmentspage", }, ["pagesep"]={ ["en"]="pagesep", + ["fr"]="seppage", }, ["pageseparatorset"]={ ["en"]="pageseparatorset", + ["fr"]="jeuseparateurpage", }, ["pageset"]={ ["en"]="pageset", + ["fr"]="jeupage", }, ["pagestarter"]={ ["en"]="pagestarter", + ["fr"]="demarreurpage", }, ["pagestate"]={ ["cs"]="pagestate", @@ -9772,6 +9986,7 @@ return { }, ["pagestopper"]={ ["en"]="pagestopper", + ["fr"]="stoppeurpage", }, ["pagestyle"]={ ["cs"]="stylstranky", @@ -9815,12 +10030,13 @@ return { }, ["period"]={ ["en"]="period", + ["fr"]="periode", }, ["place"]={ ["cs"]="umistit", ["de"]="platziere", ["en"]="place", - ["fr"]="place", + ["fr"]="placer", ["it"]="metti", ["nl"]="plaatsen", ["pe"]="بگذار", @@ -9830,7 +10046,7 @@ return { ["cs"]="umistihlavicku", ["de"]="setzekopf", ["en"]="placehead", - ["fr"]="placetete", + ["fr"]="placertete", ["it"]="mettitesta", ["nl"]="plaatskop", ["pe"]="بگذارسر", @@ -9840,7 +10056,7 @@ return { ["cs"]="predelmista", ["de"]="setzetrenner", ["en"]="placestopper", - ["fr"]="emplacementstopper", + ["fr"]="placerstoppeur", ["it"]="mettistopper", ["nl"]="plaatsafsluiter", ["pe"]="بگذارایست", @@ -9868,33 +10084,41 @@ return { }, ["prefixconnector"]={ ["en"]="prefixconnector", + ["fr"]="connecteurprefixe", }, ["prefixconversion"]={ ["en"]="prefixconversion", + ["fr"]="conversionprefixe", }, ["prefixconversionset"]={ ["en"]="prefixconversionset", + ["fr"]="jeuconversionprefixe", }, ["prefixsegments"]={ ["en"]="prefixsegments", + ["fr"]="segmentsprefixe", }, ["prefixseparatorset"]={ ["en"]="prefixseparatorset", + ["fr"]="jeuseparateurprefixe", }, ["prefixset"]={ ["en"]="prefixset", + ["fr"]="jeuprefixe", }, ["prefixstarter"]={ ["en"]="prefixstarter", + ["fr"]="demarreurprefixe", }, ["prefixstopper"]={ ["en"]="prefixstopper", + ["fr"]="stoppeurprefixe", }, ["preset"]={ ["cs"]="prednastaveni", ["de"]="voreinstellung", ["en"]="preset", - ["fr"]="prereglage", + ["fr"]="preregler", ["it"]="preimpostato", ["nl"]="preset", ["pe"]="preset", @@ -9904,7 +10128,7 @@ return { ["cs"]="nahled", ["de"]="vorschau", ["en"]="preview", - ["fr"]="previsualisation", + ["fr"]="apercu", ["it"]="anteprima", ["nl"]="preview", ["pe"]="پیش‌دید", @@ -9932,13 +10156,14 @@ return { }, ["print"]={ ["en"]="print", + ["fr"]="imprimer", ["nl"]="print", }, ["printable"]={ ["cs"]="tisknutelne", ["de"]="druckbar", ["en"]="printable", - ["fr"]="editable", + ["fr"]="imprimable", ["it"]="stampabile", ["nl"]="printbaar", ["pe"]="قابل‌چاپ", @@ -9948,7 +10173,7 @@ return { ["cs"]="process", ["de"]="process", ["en"]="process", - ["fr"]="process", + ["fr"]="traiter", ["it"]="process", ["nl"]="proces", ["pe"]="پردازش", @@ -9956,15 +10181,19 @@ return { }, ["profile"]={ ["en"]="profile", + ["fr"]="profil", }, ["properties"]={ ["en"]="properties", + ["fr"]="proprietes", }, ["pubsep"]={ ["en"]="pubsep", + ["fr"]="seppub", }, ["quotechar"]={ ["en"]="quotechar", + ["fr"]="caracitation", }, ["radius"]={ ["cs"]="polomer", @@ -9988,6 +10217,7 @@ return { }, ["range"]={ ["en"]="range", + ["fr"]="gamme", ["nl"]="bereik", }, ["reduction"]={ @@ -10012,6 +10242,7 @@ return { }, ["refcommand"]={ ["en"]="refcommand", + ["fr"]="commanderef", }, ["reference"]={ ["cs"]="odkaz", @@ -10025,15 +10256,17 @@ return { }, ["referencemethod"]={ ["en"]="referencemethod", + ["fr"]="methodereference", }, ["referenceprefix"]={ ["en"]="referenceprefix", + ["fr"]="prefixereference", }, ["referencing"]={ ["cs"]="odkazujici", ["de"]="referieren", ["en"]="referencing", - ["fr"]="referencing", + ["fr"]="referencement", ["it"]="referencing", ["nl"]="refereren", ["pe"]="مراجعه", @@ -10041,13 +10274,14 @@ return { }, ["region"]={ ["en"]="region", + ["fr"]="region", ["nl"]="gebied", }, ["regionin"]={ ["cs"]="oblastuvnitr", ["de"]="regionin", ["en"]="regionin", - ["fr"]="entreregion", + ["fr"]="regiondedans", ["it"]="entraregione", ["nl"]="gebiedin", ["pe"]="ناحیه‌درون", @@ -10057,7 +10291,7 @@ return { ["cs"]="oblastvne", ["de"]="regionaus", ["en"]="regionout", - ["fr"]="regionexterieure", + ["fr"]="regiondehors", ["it"]="esciregione", ["nl"]="gebieduit", ["pe"]="ناحیه‌بیرون", @@ -10065,21 +10299,25 @@ return { }, ["register"]={ ["en"]="register", + ["fr"]="registre", }, ["regularfeatures"]={ ["en"]="regularfeatures", + ["fr"]="fonctionnalitesordinaires", }, ["regularfont"]={ ["en"]="regularfont", + ["fr"]="policereordinaire", }, ["renderingsetup"]={ ["en"]="renderingsetup", + ["fr"]="configurationrendu", }, ["repeat"]={ ["cs"]="opakovat", ["de"]="wiederholen", ["en"]="repeat", - ["fr"]="repete", + ["fr"]="repeter", ["it"]="ripeti", ["nl"]="herhaal", ["pe"]="تکرار", @@ -10089,7 +10327,7 @@ return { ["cs"]="reset", ["de"]="reset", ["en"]="reset", - ["fr"]="reset", + ["fr"]="raz", ["it"]="reset", ["nl"]="reset", ["pe"]="بازنشانی", @@ -10117,12 +10355,13 @@ return { }, ["resources"]={ ["en"]="resources", + ["fr"]="ressources", }, ["reverse"]={ ["cs"]="reverse", ["de"]="reverse", ["en"]="reverse", - ["fr"]="inverse", + ["fr"]="inverser", ["it"]="invertito", ["nl"]="omgekeerd", ["pe"]="برعکس", @@ -10138,6 +10377,10 @@ return { ["pe"]="راست", ["ro"]="dreapta", }, + ["rightchars"]={ + ["en"]="rightchars", + ["fr"]="caracteresdroite", + }, ["rightcolor"]={ ["cs"]="barvavpravo", ["de"]="rechterfarbe", @@ -10152,7 +10395,7 @@ return { ["cs"]="rightcompoundhyphen", ["de"]="rightcompoundhyphen", ["en"]="rightcompoundhyphen", - ["fr"]="rightcompoundhyphen", + ["fr"]="traitdunioncomposedroite", ["it"]="rightcompoundhyphen", ["nl"]="rechterkoppelteken", ["pe"]="rightcompoundhyphen", @@ -10182,7 +10425,7 @@ return { ["cs"]="ramecekvpravo", ["de"]="rechterrahmen", ["en"]="rightframe", - ["fr"]="cadredroit", + ["fr"]="cadredroite", ["it"]="cornicedestra", ["nl"]="rechterkader", ["pe"]="قالب‌راست", @@ -10192,7 +10435,7 @@ return { ["cs"]="righthyphen", ["de"]="righthyphen", ["en"]="righthyphen", - ["fr"]="righthyphen", + ["fr"]="traitduniondroite", ["it"]="righthyphen", ["nl"]="righthyphen", ["pe"]="righthyphen", @@ -10222,7 +10465,7 @@ return { ["cs"]="pravyoffset", ["de"]="rechterabstand", ["en"]="rightoffset", - ["fr"]="rightoffset", + ["fr"]="decalagedroite", ["it"]="offsetdestro", ["nl"]="rechteroffset", ["pe"]="آفست‌راست", @@ -10248,6 +10491,10 @@ return { ["pe"]="نقل‌راست", ["ro"]="minicitatdreapta", }, + ["rightsample"]={ + ["en"]="rightsample", + ["fr"]="echantillondroite", + }, ["rightsentence"]={ ["cs"]="vetavpravo", ["de"]="rechtersatz", @@ -10262,7 +10509,7 @@ return { ["cs"]="rightspeech", ["de"]="rightspeech", ["en"]="rightspeech", - ["fr"]="rightspeech", + ["fr"]="discoursdroite", ["it"]="rightspeech", ["nl"]="rechteruitspraak", ["pe"]="سخنرانی‌راست", @@ -10292,7 +10539,7 @@ return { ["cs"]="textvpravo", ["de"]="rechtertext", ["en"]="righttext", - ["fr"]="textedroit", + ["fr"]="textedroite", ["it"]="testodestro", ["nl"]="rechtertekst", ["pe"]="متن‌راست", @@ -10310,12 +10557,11 @@ return { }, ["rightwords"]={ ["en"]="rightwords", - }, - ["rightchars"]={ - ["en"]="rightchars", + ["fr"]="motsdroite", }, ["roffset"]={ ["en"]="roffset", + ["fr"]="decalager", }, ["rotation"]={ ["cs"]="rotace", @@ -10331,7 +10577,7 @@ return { ["cs"]="linka", ["de"]="linie", ["en"]="rule", - ["fr"]="ligne", + ["fr"]="trait", ["it"]="linea", ["nl"]="lijn", ["pe"]="خط", @@ -10341,7 +10587,7 @@ return { ["cs"]="barvalinky", ["de"]="linienfarbe", ["en"]="rulecolor", - ["fr"]="couleurligne", + ["fr"]="couleurtrait", ["it"]="colorelinea", ["nl"]="lijnkleur", ["pe"]="رنگ‌خط", @@ -10349,13 +10595,14 @@ return { }, ["rulecommand"]={ ["en"]="rulecommand", + ["fr"]="commandetrait", ["nl"]="lijncommando", }, ["rulethickness"]={ ["cs"]="tloustkalinky", ["de"]="liniendicke", ["en"]="rulethickness", - ["fr"]="epaisseurligne", + ["fr"]="epaisseurtrait", ["it"]="spessorelinea", ["nl"]="lijndikte", ["pe"]="ضخامت‌خط", @@ -10371,12 +10618,6 @@ return { ["pe"]="همان‌صفحه", ["ro"]="aceeasipagina", }, - ["leftsample"]={ - ["en"]="leftsample", - }, - ["rightsample"]={ - ["en"]="rightsample", - }, ["sample"]={ ["cs"]="vzor", ["de"]="muster", @@ -10389,9 +10630,11 @@ return { }, ["samplesize"]={ ["en"]="samplesize", + ["fr"]="tailleechantillon", }, ["saveinlist"]={ ["en"]="saveinlist", + ["fr"]="enregistrerdansliste", }, ["scale"]={ ["cs"]="meritko", @@ -10407,7 +10650,7 @@ return { ["cs"]="rozsah", ["de"]="bereich", ["en"]="scope", - ["fr"]="scope", + ["fr"]="perimetre", ["it"]="scope", ["nl"]="scope", ["pe"]="طرح", @@ -10435,12 +10678,15 @@ return { }, ["sectionblock"]={ ["en"]="sectionblock", + ["fr"]="blocsection", }, ["sectionconversion"]={ ["en"]="sectionconversion", + ["fr"]="conversionsection", }, ["sectionconversionset"]={ ["en"]="sectionconversionset", + ["fr"]="jeuconversionsection", }, ["sectionnumber"]={ ["cs"]="cislooddilu", @@ -10454,21 +10700,27 @@ return { }, ["sectionresetset"]={ ["en"]="sectionresetset", + ["fr"]="jeurazsection", }, ["sectionsegments"]={ ["en"]="sectionsegments", + ["fr"]="segmentssection", }, ["sectionseparatorset"]={ ["en"]="sectionseparatorset", + ["fr"]="jeuseparateursection", }, ["sectionset"]={ ["en"]="sectionset", + ["fr"]="jeusection", }, ["sectionstarter"]={ ["en"]="sectionstarter", + ["fr"]="demarreursection", }, ["sectionstopper"]={ ["en"]="sectionstopper", + ["fr"]="stoppeursection", }, ["separator"]={ ["cs"]="oddelovac", @@ -10482,28 +10734,30 @@ return { }, ["separatorcolor"]={ ["en"]="separatorcolor", + ["fr"]="couleurseparateur", ["nl"]="scheiderkleur", }, ["separatorstyle"]={ ["en"]="separatorstyle", + ["fr"]="styleseparateur", ["nl"]="scheiderletter", }, ["set"]={ ["cs"]="set", ["de"]="set", ["en"]="set", - ["fr"]="set", + ["fr"]="regler", ["it"]="set", ["nl"]="set", ["pe"]="قراربده", ["ro"]="set", }, ["setups"]={ - ["comment"]="no translations", ["en"]="setups", }, ["shrink"]={ ["en"]="shrink", + ["fr"]="retrecir", ["nl"]="krimp", }, ["side"]={ @@ -10520,7 +10774,7 @@ return { ["cs"]="sidealign", ["de"]="sidealign", ["en"]="sidealign", - ["fr"]="sidealign", + ["fr"]="alignercote", ["it"]="sidealign", ["nl"]="zijuitlijnen", ["pe"]="تنظیم‌کنار", @@ -10530,7 +10784,7 @@ return { ["cs"]="sidemethod", ["de"]="sidemethod", ["en"]="sidemethod", - ["fr"]="sidemethod", + ["fr"]="methodecote", ["it"]="sidemethod", ["nl"]="zijmethode", ["pe"]="روش‌کنار", @@ -10540,7 +10794,7 @@ return { ["cs"]="bocnimezeraza", ["de"]="nebennachspatium", ["en"]="sidespaceafter", - ["fr"]="espacelateralapres", + ["fr"]="espacelatéralaprès", ["it"]="spaziolateraledopo", ["nl"]="zijnawit", ["pe"]="فضای‌کناری‌بعد", @@ -10558,15 +10812,12 @@ return { }, ["sidespaceinbetween"]={ ["en"]="sidespaceinbetween", + ["fr"]="espacelateralentre", ["nl"]="zijtussenwit", }, - ["spaceafterside"]={ - ["en"]="spaceafterside", - ["nl"]="witnazij", - }, - ["spacebeforeside"]={ - ["en"]="spacebeforeside", - ["nl"]="witvoorzij", + ["sidethreshold"]={ + ["en"]="sidethreshold", + ["fr"]="seuilcote", }, ["sign"]={ ["cs"]="znak", @@ -10578,11 +10829,16 @@ return { ["pe"]="علامت", ["ro"]="semn", }, + ["simplecommand"]={ + ["en"]="simplecommand", + ["fr"]="commandesimple", + ["nl"]="simpelcommando", + }, ["size"]={ ["cs"]="velikost", ["de"]="groesse", ["en"]="size", - ["fr"]="dimension", + ["fr"]="taille", ["it"]="dimensione", ["nl"]="formaat", ["pe"]="اندازه", @@ -10590,9 +10846,11 @@ return { }, ["slantedfeatures"]={ ["en"]="slantedfeatures", + ["fr"]="fonctionnalitesincline", }, ["slantedfont"]={ ["en"]="slantedfont", + ["fr"]="policeinclinee", }, ["small"]={ ["cs"]="male", @@ -10606,22 +10864,26 @@ return { }, ["smallcapsfeatures"]={ ["en"]="smallcapsfeatures", + ["fr"]="fonctionnalitespetitescaps", }, ["smallcapsfont"]={ ["en"]="smallcapsfont", + ["fr"]="policepetitescaps", }, ["solution"]={ ["en"]="solution", + ["fr"]="solution", ["nl"]="oplossing", }, ["sort"]={ ["en"]="sort", + ["fr"]="trier", }, ["sorttype"]={ ["cs"]="sorttype", ["de"]="sorttype", ["en"]="sorttype", - ["fr"]="sorttype", + ["fr"]="modetri", ["it"]="sorttype", ["nl"]="sortering", ["pe"]="ترتیب‌تایپ", @@ -10631,7 +10893,7 @@ return { ["cs"]="zdroj", ["de"]="quelle", ["en"]="source", - ["fr"]="origine", + ["fr"]="source", ["it"]="origine", ["nl"]="bron", ["pe"]="منبع", @@ -10651,12 +10913,17 @@ return { ["cs"]="mezeraza", ["de"]="nachspatium", ["en"]="spaceafter", - ["fr"]="espaceapres", + ["fr"]="espaceaprès", ["it"]="spaziodopo", ["nl"]="nawit", ["pe"]="فضا‌بعداز", ["ro"]="spatiudupa", }, + ["spaceafterside"]={ + ["en"]="spaceafterside", + ["fr"]="espaceaprèscoté", + ["nl"]="witnazij", + }, ["spacebefore"]={ ["cs"]="mezerapred", ["de"]="vorspatium", @@ -10667,11 +10934,16 @@ return { ["pe"]="فضا‌قبل‌از", ["ro"]="spatiuinainte", }, + ["spacebeforeside"]={ + ["en"]="spacebeforeside", + ["fr"]="espaceavantcote", + ["nl"]="witvoorzij", + }, ["spaceinbetween"]={ ["cs"]="spaceinbetween", ["de"]="spaceinbetween", ["en"]="spaceinbetween", - ["fr"]="spaceinbetween", + ["fr"]="espaceentre", ["it"]="spaceinbetween", ["nl"]="tussenwit", ["pe"]="فضا‌دربین", @@ -10689,12 +10961,13 @@ return { }, ["specification"]={ ["en"]="specification", + ["fr"]="specification", }, ["split"]={ ["cs"]="split", ["de"]="split", ["en"]="split", - ["fr"]="split", + ["fr"]="partager", ["it"]="separa", ["nl"]="splitsen", ["pe"]="شکافتن", @@ -10704,7 +10977,7 @@ return { ["cs"]="splitcolor", ["de"]="splitcolor", ["en"]="splitcolor", - ["fr"]="splitcolor", + ["fr"]="couleurpartage", ["it"]="splitcolor", ["nl"]="splitskleur", ["pe"]="شکافتن‌رنگ", @@ -10714,7 +10987,7 @@ return { ["cs"]="splitmethod", ["de"]="splitmethod", ["en"]="splitmethod", - ["fr"]="splitmethod", + ["fr"]="methodepartage", ["it"]="splitmethod", ["nl"]="splitsmethode", ["pe"]="روش‌شکافتن", @@ -10724,7 +10997,7 @@ return { ["cs"]="splitoffset", ["de"]="splitoffset", ["en"]="splitoffset", - ["fr"]="splitoffset", + ["fr"]="decalagepartage", ["it"]="splitoffset", ["nl"]="splitsoffset", ["pe"]="شکافتن‌آفست", @@ -10734,7 +11007,7 @@ return { ["cs"]="spot", ["de"]="spot", ["en"]="spot", - ["fr"]="spot", + ["fr"]="tondirect", ["it"]="spot", ["nl"]="spot", ["pe"]="لکه", @@ -10744,7 +11017,7 @@ return { ["cs"]="stack", ["de"]="stack", ["en"]="stack", - ["fr"]="stack", + ["fr"]="pile", ["it"]="stack", ["nl"]="stapel", ["pe"]="توده", @@ -10752,13 +11025,14 @@ return { }, ["stackname"]={ ["en"]="stackname", + ["fr"]="nompile", ["nl"]="stapelnaam", }, ["start"]={ ["cs"]="start", ["de"]="start", ["en"]="start", - ["fr"]="demarre", + ["fr"]="début", ["it"]="inizia", ["nl"]="start", ["pe"]="شروع", @@ -10766,13 +11040,14 @@ return { }, ["starter"]={ ["en"]="starter", + ["fr"]="demarreur", ["nl"]="opener", }, ["state"]={ ["cs"]="status", ["de"]="status", ["en"]="state", - ["fr"]="etat", + ["fr"]="état", ["it"]="stato", ["nl"]="status", ["pe"]="وضعیت", @@ -10782,7 +11057,7 @@ return { ["cs"]="krok", ["de"]="schritt", ["en"]="step", - ["fr"]="pas", + ["fr"]="etape", ["it"]="passo", ["nl"]="stap", ["pe"]="گام", @@ -10792,7 +11067,7 @@ return { ["cs"]="stop", ["de"]="stop", ["en"]="stop", - ["fr"]="stoppe", + ["fr"]="fin", ["it"]="termina", ["nl"]="stop", ["pe"]="پایان", @@ -10802,7 +11077,7 @@ return { ["cs"]="predel", ["de"]="abschnitttrenner", ["en"]="stopper", - ["fr"]="taquet", + ["fr"]="stoppeur", ["it"]="stopper", ["nl"]="afsluiter", ["pe"]="ایست", @@ -10812,7 +11087,7 @@ return { ["cs"]="natahnout", ["de"]="strecken", ["en"]="stretch", - ["fr"]="etire", + ["fr"]="etirer", ["it"]="dilata", ["nl"]="rek", ["pe"]="کشیدن", @@ -10820,25 +11095,18 @@ return { }, ["strip"]={ ["en"]="strip", + ["fr"]="bande", }, ["strut"]={ ["cs"]="strut", ["de"]="strut", ["en"]="strut", - ["fr"]="strut", + ["fr"]="entretoise", ["it"]="strut", ["nl"]="strut", ["pe"]="بست", ["ro"]="strut", }, - ["numberstrut"]={ - ["en"]="numberstrut", - ["nl"]="nummerstrut", - }, - ["titlestrut"]={ - ["en"]="titlestrut", - ["nl"]="titelstrut", - }, ["style"]={ ["cs"]="pismeno", ["de"]="stil", @@ -10849,6 +11117,11 @@ return { ["pe"]="سبک", ["ro"]="stil", }, + ["stylealternative"]={ + ["en"]="stylealternative", + ["fr"]="variantestyle", + ["nl"]="stylevariant", + }, ["sub"]={ ["cs"]="pod", ["de"]="unter", @@ -10873,7 +11146,7 @@ return { ["cs"]="suffix", ["de"]="suffix", ["en"]="suffix", - ["fr"]="suffix", + ["fr"]="suffixe", ["it"]="suffix", ["nl"]="suffix", ["pe"]="پسوند", @@ -10881,23 +11154,29 @@ return { }, ["suffixseparator"]={ ["en"]="suffixseparator", + ["fr"]="separateursuffixe", ["nl"]="suffixscheider", }, ["suffixstopper"]={ ["en"]="suffixstopper", + ["fr"]="stoppeursuffixe", ["nl"]="suffixafsluiter", }, ["surnamefirstnamesep"]={ ["en"]="surnamefirstnamesep", + ["fr"]="sepnomfamilleprenom", }, ["surnameinitialsep"]={ ["en"]="surnameinitialsep", + ["fr"]="sepnomfamilleinitial", }, ["surnamesep"]={ ["en"]="surnamesep", + ["fr"]="seprenom", }, ["svgstyle"]={ ["en"]="svgstyle", + ["fr"]="stylesvg", }, ["sx"]={ ["cs"]="sx", @@ -10923,7 +11202,7 @@ return { ["cs"]="symzarovnani", ["de"]="symausrichtung", ["en"]="symalign", - ["fr"]="symalignement", + ["fr"]="alignersym", ["it"]="symallinea", ["nl"]="symuitlijnen", ["pe"]="تنظیم‌نماد", @@ -10941,6 +11220,7 @@ return { }, ["symbolcommand"]={ ["en"]="symbolcommand", + ["fr"]="commandesymbole", }, ["symbolset"]={ ["cs"]="sadasymbolu", @@ -10996,7 +11276,7 @@ return { ["cs"]="synonymcommand", ["de"]="synonymbefehl", ["en"]="synonymcommand", - ["fr"]="synonymcommand", + ["fr"]="commandesynonyme", ["it"]="synonymcommand", ["nl"]="synoniemcommando", ["pe"]="synonymcommand", @@ -11034,6 +11314,7 @@ return { }, ["textalign"]={ ["en"]="textalign", + ["fr"]="alignertexte", }, ["textcolor"]={ ["cs"]="barvatextu", @@ -11099,7 +11380,7 @@ return { ["cs"]="textmethod", ["de"]="textmethod", ["en"]="textmethod", - ["fr"]="textmethod", + ["fr"]="methodetexte", ["it"]="textmethod", ["nl"]="tekstmethode", ["pe"]="روش‌متن", @@ -11157,15 +11438,12 @@ return { }, ["threshold"]={ ["en"]="threshold", + ["fr"]="seuil", }, - ["sidethreshold"]={ - ["en"]="sidethreshold", - }, - ["displaythreshold"]={ - ["en"]="displaythreshold", - }, - ["inlinethreshold"]={ - ["en"]="inlinethreshold", + ["time"]={ + ["en"]="time", + ["fr"]="temps", + ["nl"]="tijd", }, ["title"]={ ["cs"]="titul", @@ -11187,15 +11465,11 @@ return { ["pe"]="رنگ‌عنوان", ["ro"]="culoaretitlu", }, - ["simplecommand"]={ - ["en"]="simplecommand", - ["nl"]="simpelcommando", - }, ["titlecommand"]={ ["cs"]="titlecommand", ["de"]="titlecommand", ["en"]="titlecommand", - ["fr"]="titlecommand", + ["fr"]="commandetitre", ["it"]="titlecommand", ["nl"]="titelcommando", ["pe"]="فرمان‌عنوان", @@ -11215,7 +11489,7 @@ return { ["cs"]="titleleft", ["de"]="titleleft", ["en"]="titleleft", - ["fr"]="titleleft", + ["fr"]="gauchetitre", ["it"]="titleleft", ["nl"]="titellinks", ["pe"]="عنوان‌چپ", @@ -11225,12 +11499,17 @@ return { ["cs"]="titleright", ["de"]="titleright", ["en"]="titleright", - ["fr"]="titleright", + ["fr"]="droitetitre", ["it"]="titleright", ["nl"]="titelrechts", ["pe"]="عنوان‌راست", ["ro"]="titleright", }, + ["titlestrut"]={ + ["en"]="titlestrut", + ["fr"]="entretoisetitre", + ["nl"]="titelstrut", + }, ["titlestyle"]={ ["cs"]="styltitulek", ["de"]="titelstil", @@ -11253,6 +11532,7 @@ return { }, ["toffset"]={ ["en"]="toffset", + ["fr"]="decalaget", }, ["tolerance"]={ ["cs"]="tolerance", @@ -11268,7 +11548,7 @@ return { ["cs"]="vrsek", ["de"]="oben", ["en"]="top", - ["fr"]="sup", + ["fr"]="haut", ["it"]="cima", ["nl"]="boven", ["pe"]="بالا", @@ -11276,13 +11556,14 @@ return { }, ["topcommand"]={ ["en"]="topcommand", + ["fr"]="commandehaut", ["nl"]="bovencommando", }, ["topdistance"]={ ["cs"]="vzdalenostvrsku", ["de"]="obenabstand", ["en"]="topdistance", - ["fr"]="distancesup", + ["fr"]="distancehaut", ["it"]="distanzacima", ["nl"]="bovenafstand", ["pe"]="فاصله‌بالا", @@ -11292,7 +11573,7 @@ return { ["cs"]="rameceknahore", ["de"]="obenrahmen", ["en"]="topframe", - ["fr"]="cadresup", + ["fr"]="cadrehaut", ["it"]="cornicecima", ["nl"]="bovenkader", ["pe"]="قالب‌راست", @@ -11302,7 +11583,7 @@ return { ["cs"]="offsetvrsku", ["de"]="obenoffset", ["en"]="topoffset", - ["fr"]="decalagesup", + ["fr"]="decalagehaut", ["it"]="offsetcima", ["nl"]="bovenoffset", ["pe"]="آفست‌بالا", @@ -11312,7 +11593,7 @@ return { ["cs"]="svrchnimezera", ["de"]="kopfspatium", ["en"]="topspace", - ["fr"]="espacesup", + ["fr"]="espacehaut", ["it"]="spaziocima", ["nl"]="kopwit", ["pe"]="فضای‌بالا", @@ -11322,7 +11603,7 @@ return { ["cs"]="statusvrsku", ["de"]="statusoben", ["en"]="topstate", - ["fr"]="etatsup", + ["fr"]="etathaut", ["it"]="statocima", ["nl"]="bovenstatus", ["pe"]="وضعیت‌بالا", @@ -11330,22 +11611,26 @@ return { }, ["totalnumber"]={ ["en"]="totalnumber", + ["fr"]="nombretotal", }, ["transform"]={ - ["en"]="transform", - ["nl"]="transformatie", + ["en"]="transform", + ["fr"]="transformer", + ["nl"]="transformatie", }, ["translate"]={ ["en"]="translate", + ["fr"]="traduire", }, ["trimoffset"]={ ["en"]="trimoffset", + ["fr"]="decalagecoupe", }, ["type"]={ ["cs"]="typ", ["de"]="typ", ["en"]="type", - ["fr"]="type", + ["fr"]="transcrire", ["it"]="type", ["nl"]="type", ["pe"]="تایپ", @@ -11373,12 +11658,13 @@ return { }, ["up"]={ ["en"]="up", + ["fr"]="enhaut", }, ["urlalternative"]={ ["cs"]="urlalternativa", ["de"]="urlalternative", ["en"]="urlalternative", - ["fr"]="alternativeurl", + ["fr"]="varianteurl", ["it"]="alternativaurl", ["nl"]="urlvariant", ["pe"]="urlalternative", @@ -11394,6 +11680,10 @@ return { ["pe"]="urlspace", ["ro"]="spatiuurl", }, + ["userpassword"]={ + ["en"]="userpassword", + ["fr"]="motdepasseutilisateur", + }, ["validate"]={ ["cs"]="validovat", ["de"]="validieren", @@ -11406,13 +11696,14 @@ return { }, ["values"]={ ["en"]="values", + ["fr"]="valeurs", ["nl"]="waarden", }, ["vcommand"]={ ["cs"]="vprikaz", ["de"]="vbefehl", ["en"]="vcommand", - ["fr"]="vcommande", + ["fr"]="commandev", ["it"]="vcomando", ["nl"]="vcommando", ["pe"]="vcommand", @@ -11420,37 +11711,48 @@ return { }, ["vcompact"]={ ["en"]="vcompact", + ["fr"]="compactv", ["nl"]="vcomprimeer", }, ["vector"]={ ["en"]="vector", + ["fr"]="vecteur", ["nl"]="vector", }, + ["veroffset"]={ + ["cs"]="offsethlavicky", + ["de"]="kopfoffset", + ["en"]="veroffset", + ["fr"]="decalagever", + ["it"]="veroffset", + ["nl"]="kopoffset", + ["pe"]="آفست‌عم", + ["ro"]="veroffset", + }, ["vertical"]={ ["cs"]="vertikalne", ["de"]="vertikal", ["en"]="vertical", - ["fr"]="verticale", + ["fr"]="vertical", ["it"]="verticale", ["nl"]="vertikaal", ["pe"]="عمودی", ["ro"]="vertical", }, - ["veroffset"]={ - ["cs"]="offsethlavicky", - ["de"]="kopfoffset", - ["en"]="veroffset", - ["fr"]="veroffset", - ["it"]="veroffset", - ["nl"]="kopoffset", - ["pe"]="آفست‌عم", - ["ro"]="veroffset", + ["vfactor"]={ + ["cs"]="vfaktor", + ["de"]="vfaktor", + ["en"]="vfactor", + ["fr"]="facteurv", + ["it"]="vfactor", + ["nl"]="vfactor", + ["ro"]="vfactor", }, ["vfil"]={ ["cs"]="vfil", ["de"]="vfil", ["en"]="vfil", - ["fr"]="vfil", + ["fr"]="remplissagev", ["it"]="vfil", ["nl"]="vfil", ["pe"]="vfil", @@ -11458,12 +11760,13 @@ return { }, ["viewerprefix"]={ ["en"]="viewerprefix", + ["fr"]="prefixevisualisateur", }, ["voffset"]={ ["cs"]="voffset", ["de"]="voffset", ["en"]="voffset", - ["fr"]="voffset", + ["fr"]="decalagev", ["it"]="voffset", ["nl"]="voffset", ["pe"]="آفست‌ع", @@ -11471,12 +11774,13 @@ return { }, ["vonsep"]={ ["en"]="vonsep", + ["fr"]="sepvon", }, ["way"]={ ["cs"]="zpusob", ["de"]="art", ["en"]="way", - ["fr"]="mode", + ["fr"]="maniere", ["it"]="modo", ["nl"]="wijze", ["pe"]="راه", @@ -11486,7 +11790,7 @@ return { ["cs"]="sfaktor", ["de"]="bfaktor", ["en"]="wfactor", - ["fr"]="facteurlargeur", + ["fr"]="facteurw", ["it"]="wfactor", ["nl"]="bfactor", ["pe"]="wfactor", @@ -11514,12 +11818,18 @@ return { }, ["words"]={ ["en"]="words", + ["fr"]="mots", + }, + ["xanchor"]={ + ["en"]="xanchor", + ["fr"]="ancrex", + ["nl"]="xanker", }, ["xfactor"]={ ["cs"]="xfaktor", ["de"]="xfaktor", ["en"]="xfactor", - ["fr"]="xfactor", + ["fr"]="facteurx", ["it"]="xfactor", ["nl"]="xfactor", ["pe"]="فاکتورایکس", @@ -11527,6 +11837,7 @@ return { }, ["xhtml"]={ ["en"]="xhtml", + ["fr"]="xhtml", }, ["xmax"]={ ["cs"]="xmax", @@ -11540,16 +11851,13 @@ return { }, ["xmlsetup"]={ ["en"]="xmlsetup", - }, - ["xanchor"]={ - ["en"]="xanchor", - ["nl"]="xanker", + ["fr"]="configurationxml", }, ["xoffset"]={ ["cs"]="xoffset", ["de"]="xoffset", ["en"]="xoffset", - ["fr"]="xoffset", + ["fr"]="decalagex", ["it"]="xoffset", ["nl"]="xoffset", ["pe"]="آفست‌ایکس", @@ -11559,7 +11867,7 @@ return { ["cs"]="xmeritko", ["de"]="xformat", ["en"]="xscale", - ["fr"]="xscale", + ["fr"]="echellex", ["it"]="xscale", ["nl"]="xschaal", ["pe"]="مقیاس‌ایکس", @@ -11569,17 +11877,22 @@ return { ["cs"]="xkrok", ["de"]="xschritt", ["en"]="xstep", - ["fr"]="xstep", + ["fr"]="etapex", ["it"]="xstep", ["nl"]="xstap", ["pe"]="گام‌ایکس", ["ro"]="xstep", }, + ["yanchor"]={ + ["en"]="yanchor", + ["fr"]="ancrey", + ["nl"]="yanker", + }, ["yfactor"]={ ["cs"]="yfaktor", ["de"]="yfaktor", ["en"]="yfactor", - ["fr"]="yfactor", + ["fr"]="facteury", ["it"]="yfactor", ["nl"]="yfactor", ["pe"]="فاکتوروای", @@ -11595,15 +11908,11 @@ return { ["pe"]="ymax", ["ro"]="ymax", }, - ["yanchor"]={ - ["en"]="yanchor", - ["nl"]="yanker", - }, ["yoffset"]={ ["cs"]="yoffset", ["de"]="yoffset", ["en"]="yoffset", - ["fr"]="yoffset", + ["fr"]="decalagey", ["it"]="yoffset", ["nl"]="yoffset", ["pe"]="آفست‌وای", @@ -11613,7 +11922,7 @@ return { ["cs"]="ymeritko", ["de"]="yformat", ["en"]="yscale", - ["fr"]="yscale", + ["fr"]="echelley", ["it"]="yscale", ["nl"]="yschaal", ["pe"]="مقیاس‌وای", @@ -11623,25 +11932,19 @@ return { ["cs"]="ykrok", ["de"]="yschritt", ["en"]="ystep", - ["fr"]="ystep", + ["fr"]="etapey", ["it"]="ystep", ["nl"]="ystap", ["pe"]="گام‌وای", ["ro"]="ystep", }, - ["ownerpassword"]={ - ["en"]="ownerpassword", - }, - ["userpassword"]={ - ["en"]="userpassword", - }, }, ["elements"]={ ["answerlines"]={ ["cs"]="answerlines", ["de"]="answerlines", ["en"]="answerlines", - ["fr"]="answerlines", + ["fr"]="lignesreponse", ["it"]="answerlines", ["nl"]="antwoordregels", ["pe"]="answerlines", @@ -11651,7 +11954,7 @@ return { ["cs"]="answerspace", ["de"]="answerspace", ["en"]="answerspace", - ["fr"]="answerspace", + ["fr"]="espacereponse", ["it"]="answerspace", ["nl"]="antwoordruimte", ["pe"]="answerspace", @@ -11661,7 +11964,7 @@ return { ["cs"]="zacatek", ["de"]="anfang", ["en"]="begin", - ["fr"]="debut", + ["fr"]="commencer", ["it"]="inizio", ["nl"]="beginvan", ["pe"]="عنصرها", @@ -11671,7 +11974,7 @@ return { ["cs"]="uplny", ["de"]="vollende", ["en"]="complete", - ["fr"]="complete", + ["fr"]="complet", ["it"]="completo", ["nl"]="volledige", ["pe"]="کامل", @@ -11701,7 +12004,7 @@ return { ["cs"]="konec", ["de"]="ende", ["en"]="end", - ["fr"]="fin", + ["fr"]="terminer", ["it"]="fine", ["nl"]="eindvan", ["pe"]="انتها", @@ -11721,7 +12024,7 @@ return { ["cs"]="ziskat", ["de"]="get", ["en"]="get", - ["fr"]="obtient", + ["fr"]="obtenir", ["it"]="prendi", ["nl"]="haal", ["pe"]="بگیر", @@ -11731,7 +12034,7 @@ return { ["cs"]="zvysit", ["de"]="erhoehen", ["en"]="increment", - ["fr"]="incremente", + ["fr"]="incrementer", ["it"]="incrementa", ["nl"]="verhoog", ["pe"]="افزایش", @@ -11761,7 +12064,7 @@ return { ["cs"]="nacist", ["de"]="laden", ["en"]="load", - ["fr"]="charge", + ["fr"]="charger", ["it"]="carica", ["nl"]="laad", ["pe"]="بارگذاشتن", @@ -11781,7 +12084,7 @@ return { ["cs"]="zlom", ["de"]="umbruch", ["en"]="makeup", - ["fr"]="makeup", + ["fr"]="composition", ["it"]="makeup", ["nl"]="opmaak", ["pe"]="آرایش", @@ -11801,7 +12104,7 @@ return { ["cs"]="umisti", ["de"]="platziere", ["en"]="place", - ["fr"]="place", + ["fr"]="placer", ["it"]="metti", ["nl"]="plaats", ["pe"]="مکان", @@ -11841,7 +12144,7 @@ return { ["cs"]="viz", ["de"]="sieh", ["en"]="see", - ["fr"]="voit", + ["fr"]="voir", ["it"]="vedi", ["nl"]="zie", ["pe"]="ببینید", @@ -11851,7 +12154,7 @@ return { ["cs"]="nastaveni", ["de"]="stelle", ["en"]="setup", - ["fr"]="regle", + ["fr"]="configurer", ["it"]="imposta", ["nl"]="stel", ["pe"]="بارگذاری", @@ -11861,7 +12164,7 @@ return { ["cs"]="start", ["de"]="start", ["en"]="start", - ["fr"]="demarre", + ["fr"]="début", ["it"]="inizia", ["nl"]="start", ["pe"]="شروع", @@ -11871,7 +12174,7 @@ return { ["cs"]="stop", ["de"]="stop", ["en"]="stop", - ["fr"]="stoppe", + ["fr"]="fin", ["it"]="termina", ["nl"]="stop", ["pe"]="پایان", @@ -11891,6114 +12194,6383 @@ return { ["cs"]="opis", ["de"]="type", ["en"]="type", - ["fr"]="type", + ["fr"]="transcrire", ["it"]="type", ["nl"]="type", ["pe"]="تایپ", ["ro"]="type", }, }, - ["variables"]={ - ["aside"]={ - ["en"]="aside", + ["setupstrings"]={ + ["cd:angle-l"]={ + ["en"]="<<...>>", }, - ["ordinal"]={ - ["en"]="ordinal", + ["cd:angle-s"]={ + ["en"]="<<...>>", }, - ["Ordinal"]={ - ["en"]="Ordinal", + ["cd:apply-l"]={ + ["en"]="[..,..=>..,..]", }, - ["Addition"]={ - ["cs"]="Pridavek", - ["de"]="Zusatz", - ["en"]="Addition", - ["fr"]="Ajout", - ["it"]="Aggiunta", - ["nl"]="Toevoeging", - ["pe"]="جمع", - ["ro"]="Adaugare", + ["cd:apply-s"]={ + ["en"]="[..=>..]", }, - ["Alphabetic"]={ - ["en"]="Alphabetic", + ["cd:assignment-l"]={ + ["en"]="[..,..=..,..]", + ["lua"]="{ ..,..=..,.. } ", }, - ["Balloon"]={ - ["cs"]="Bublinka", - ["de"]="Ballon", - ["en"]="Balloon", - ["fr"]="Ballon", - ["it"]="Pallone", - ["nl"]="Ballon", - ["pe"]="بادکنک", - ["ro"]="Balon", + ["cd:assignment-s"]={ + ["en"]="[..=..]", + ["lua"]="{ ..=.. } ", }, - ["Cap"]={ - ["cs"]="Kap", - ["de"]="Kap", - ["en"]="Cap", - ["fr"]="Cap", - ["it"]="Cap", - ["nl"]="Kap", - ["pe"]="Cap", - ["ro"]="Cap", + ["cd:assignmentbraces-l"]={ + ["en"]="{..,..=..,..}", }, - ["Capital"]={ - ["cs"]="Kapitalky", - ["de"]="Versalien", - ["en"]="Capital", - ["fr"]="Capitale", - ["it"]="Maiuscolo", - ["nl"]="Kapitaal", - ["pe"]="Capital", - ["ro"]="Majuscula", + ["cd:assignmentbraces-s"]={ + ["en"]="{..=..}", }, - ["Character"]={ - ["cs"]="Pismeno", - ["de"]="Buchstabe", - ["en"]="Character", - ["fr"]="Caratere", - ["it"]="Lettera", - ["nl"]="Letter", - ["pe"]="Character", - ["ro"]="Caracter", + ["cd:assignmentbrackets-l"]={ + ["en"]="[..,..=..,..]", + ["lua"]="{ ..,..=..,.. } ", }, - ["Characters"]={ - ["cs"]="Pismena", - ["de"]="Buchstaben", - ["en"]="Characters", - ["fr"]="Caracteres", - ["it"]="Lettere", - ["nl"]="Letters", - ["pe"]="Characters", - ["ro"]="Caractere", + ["cd:assignmentbrackets-s"]={ + ["en"]="[..=..]", + ["lua"]="{ ..=.. } ", }, - ["CloseDocument"]={ - ["cs"]="ZavritDokument", - ["de"]="SchliesseDokument", - ["en"]="CloseDocument", - ["fr"]="FermeDocument", - ["it"]="ChiudiDocumento", - ["nl"]="SluitDocument", - ["pe"]="بستن‌نوشتار", - ["ro"]="InchideDocument", + ["cd:assignmentparentheses-l"]={ + ["en"]="(..,..=..,..)", }, - ["ExitViewer"]={ - ["cs"]="UkoncitProhlizec", - ["de"]="BeendeViewer", - ["en"]="ExitViewer", - ["fr"]="SortVisualisateur", - ["it"]="EsciVisualizzatore", - ["nl"]="VerlaatViewer", - ["pe"]="خروج‌نمایشگر", - ["ro"]="IesireVizualizator", + ["cd:assignmentparentheses-s"]={ + ["en"]="(..=..)", }, - ["FirstPage"]={ - ["cs"]="PrvniStrana", - ["de"]="ErsteSeite", - ["en"]="FirstPage", - ["fr"]="PremierePage", - ["it"]="PrimaPagina", - ["nl"]="EerstePagina", - ["pe"]="صفحه‌اول", - ["ro"]="PrimaPagina", + ["cd:braces-l"]={ + ["en"]="{...,...}", + ["lua"]=".. ... ..", }, - ["FitHeight"]={ - ["cs"]="FitHeight", - ["de"]="HoehePassend", - ["en"]="FitHeight", - ["fr"]="AjusteHauteur", - ["it"]="FitHeight", - ["nl"]="HoogtePassend", - ["pe"]="پرکردن‌ارتفاع", - ["ro"]="AjustatInaltime", + ["cd:braces-s"]={ + ["en"]="{...}", + ["lua"]="\"...\"", }, - ["FitWidth"]={ - ["cs"]="FitWidth", - ["de"]="BreitePassend", - ["en"]="FitWidth", - ["fr"]="AjusteLargeur", - ["it"]="FitWidth", - ["nl"]="BreedtePassend", - ["pe"]="پرکردن‌عرض", - ["ro"]="AjustatLatime", + ["cd:brackets-l"]={ + ["en"]="[...,...]", + ["lua"]="{..., ...}", }, - ["GotoPage"]={ - ["cs"]="JdiNaStranku", - ["de"]="GotoPage", - ["en"]="GotoPage", - ["fr"]="VaalaPage", - ["it"]="VaiAPagina", - ["nl"]="GaNaarPagina", - ["pe"]="برو‌به‌صفحه", - ["ro"]="LaPagina", + ["cd:brackets-s"]={ + ["en"]="[...]", + ["lua"]="{ ... }", }, - ["Greek"]={ - ["cs"]="Recky", - ["de"]="Griechisch", - ["en"]="Greek", - ["fr"]="Grec", - ["it"]="Greco", - ["nl"]="Grieks", - ["pe"]="یونانی", - ["ro"]="Grec", + ["cd:buffer"]={ + ["cs"]="buffer", + ["de"]="buffer", + ["en"]="buffer", + ["fr"]="tampon", + ["it"]="buffer", + ["nl"]="buffer", + ["ro"]="buffer", }, - ["Help"]={ - ["cs"]="Napoveda", - ["de"]="Hilfe", - ["en"]="Help", - ["fr"]="Aide", - ["it"]="Aiuto", - ["nl"]="Help", - ["pe"]="کمک", - ["ro"]="Ajutor", + ["cd:case-l"]={ + ["en"]="\\case ", }, - ["HideField"]={ - ["cs"]="SkryjPole", - ["de"]="VerbergeFeld", - ["en"]="HideField", - ["fr"]="CacheChamp", - ["it"]="NascondiCampo", - ["nl"]="VerbergVeld", - ["pe"]="پنهان‌میدان", - ["ro"]="AscundeCamp", + ["cd:case-s"]={ + ["en"]="\\case ", }, - ["HideLayer"]={ - ["cs"]="HideLayer", - ["de"]="HideLayer", - ["en"]="HideLayer", - ["fr"]="CacheCalque", - ["it"]="HideLayer", - ["nl"]="VerbergLaag", - ["pe"]="پنهان‌لایه", - ["ro"]="HideLayer", + ["cd:category"]={ + ["cs"]="category", + ["de"]="category", + ["en"]="category", + ["fr"]="categorie", + ["it"]="category", + ["nl"]="category", + ["ro"]="category", }, - ["Key"]={ - ["cs"]="Klavesa", - ["de"]="Schluessel", - ["en"]="Key", - ["fr"]="Cle", - ["it"]="Tasto", - ["nl"]="Sleutel", - ["pe"]="کلید", - ["ro"]="Cheie", + ["cd:character"]={ + ["cs"]="character", + ["de"]="character", + ["en"]="character", + ["fr"]="caractere", + ["it"]="character", + ["nl"]="karakter", + ["ro"]="character", }, - ["LastPage"]={ - ["cs"]="PosledniStrana", - ["de"]="LetzteSeite", - ["en"]="LastPage", - ["fr"]="DernierePage", - ["it"]="UltimaPagina", - ["nl"]="LaatstePagina", - ["pe"]="صفحه‌آخر", - ["ro"]="UltimaPagina", + ["cd:color"]={ + ["cs"]="color", + ["de"]="color", + ["en"]="color", + ["fr"]="couleur", + ["it"]="color", + ["nl"]="kleur", + ["ro"]="color", }, - ["LoadForm"]={ - ["cs"]="NacistFormular", - ["de"]="LadeFormular", - ["en"]="LoadForm", - ["fr"]="ChargeForm", - ["it"]="CaricaForm", - ["nl"]="LaadFormulier", - ["pe"]="بارگذاشتن‌فرم", - ["ro"]="IncarcaFormular", + ["cd:column"]={ + ["cs"]="column", + ["de"]="column", + ["en"]="column", + ["fr"]="colonne", + ["it"]="column", + ["nl"]="kolom", + ["ro"]="column", }, - ["MONTH"]={ - ["cs"]="MESIC", - ["de"]="MONAT", - ["en"]="MONTH", - ["fr"]="MOIS", - ["it"]="MESE", - ["nl"]="MAAND", - ["pe"]="ماه", - ["ro"]="LUNA", + ["cd:command"]={ + ["cs"]="Befehl", + ["de"]="Befehl", + ["en"]="command", + ["fr"]="commande", + ["it"]="Befehl", + ["nl"]="commando", + ["ro"]="Befehl", }, - ["New"]={ - ["cs"]="Novy", - ["de"]="Neu", - ["en"]="New", - ["fr"]="Nouveau", - ["it"]="Nuovo", - ["nl"]="Nieuw", - ["pe"]="جدید", - ["ro"]="Nou", + ["cd:content"]={ + ["cs"]="content", + ["de"]="content", + ["en"]="content", + ["fr"]="contenu", + ["it"]="content", + ["nl"]="inhoud", + ["ro"]="content", }, - ["NextJump"]={ - ["cs"]="NasledujiciSkok", - ["de"]="NaechsterSprung", - ["en"]="NextJump", - ["fr"]="SautSuivant", - ["it"]="SaltoSuccessivo", - ["nl"]="VolgendeSprong", - ["pe"]="پرش‌بعدی", - ["ro"]="SaltUrmator", + ["cd:content-l"]={ + ["en"]="{.. ... ..}", + ["lua"]="\".. ... ..\"", }, - ["NextPage"]={ - ["cs"]="DalsiStrana", - ["de"]="FolgendeSeite", - ["en"]="NextPage", - ["fr"]="PageSuivante", - ["it"]="PaginaSuccessiva", - ["nl"]="VolgendePagina", - ["pe"]="صفحه‌بعدی", - ["ro"]="PaginaUrmatoare", + ["cd:content-s"]={ + ["en"]="{...}", + ["lua"]="\"...\"", }, - ["Numbers"]={ - ["cs"]="Cisla", - ["de"]="Ziffern", - ["en"]="Numbers", - ["fr"]="Numeros", - ["it"]="Numeri", - ["nl"]="Cijfers", - ["pe"]="شماره‌ها", - ["ro"]="Numere", + ["cd:csname"]={ + ["cs"]="csname", + ["de"]="csname", + ["en"]="csname", + ["fr"]="nomsc", + ["it"]="csname", + ["nl"]="naam", + ["ro"]="csname", }, - ["OpenNamedDocument"]={ - ["cs"]="OpenNamedDocument", - ["de"]="OpenNamedDocument", - ["en"]="OpenNamedDocument", - ["fr"]="OuvreDocumentNomme", - ["it"]="OpenNamedDocument", - ["nl"]="OpenDocumentOpNaam", - ["pe"]="بازکردن‌نوشتار‌ذخیره‌شده", - ["ro"]="OpenNamedDocument", + ["cd:csname-l"]={ + ["en"]="\\...", }, - ["Paragraph"]={ - ["cs"]="Odstavec", - ["de"]="Absatz", - ["en"]="Paragraph", - ["fr"]="Paragraphe", - ["it"]="Capoverso", - ["nl"]="Paragraaf", - ["pe"]="پاراگراف", - ["ro"]="Paragraf", + ["cd:csname-s"]={ + ["en"]="\\...", }, - ["PauseMovie"]={ - ["cs"]="PozastavitFilm", - ["de"]="PauseFilm", - ["en"]="PauseMovie", - ["fr"]="PauseFilm", - ["it"]="PausaFilm", - ["nl"]="PauzeerFilm", - ["pe"]="ایست‌فیلم", - ["ro"]="PauzaFilm", + ["cd:delimiter"]={ + ["cs"]="delimiter", + ["de"]="delimiter", + ["en"]="delimiter", + ["fr"]="delimiteur", + ["it"]="delimiter", + ["nl"]="delimiter", + ["ro"]="delimiter", }, - ["PauseRendering"]={ - ["cs"]="PauseRendering", - ["de"]="PauseRendering", - ["en"]="PauseRendering", - ["fr"]="PauseRendering", - ["it"]="PauseRendering", - ["nl"]="PauzeerRendering", - ["pe"]="توقف‌تعبیر", - ["ro"]="PauseRendering", + ["cd:destination"]={ + ["cs"]="destination", + ["de"]="destination", + ["en"]="destination", + ["fr"]="destination", + ["it"]="destination", + ["nl"]="bestemming", + ["ro"]="destination", }, - ["PauseSound"]={ - ["cs"]="PozastavitZvuk", - ["de"]="PauseSound", - ["en"]="PauseSound", - ["fr"]="PauseSon", - ["it"]="PausaSuono", - ["nl"]="PauzeerGeluid", - ["pe"]="ایست‌صدا", - ["ro"]="PauzaSunet", + ["cd:destination-l"]={ + ["en"]="[..,{..[ref,..]},..]", }, - ["PreviousJump"]={ - ["cs"]="PredchoziSkok", - ["de"]="VorigerSprung", - ["en"]="PreviousJump", - ["fr"]="SautPrecedent", - ["it"]="SaltoPrecedente", - ["nl"]="VorigeSprong", - ["pe"]="پرش‌قبلی", - ["ro"]="SaltPrecedent", + ["cd:destination-s"]={ + ["en"]="[{..[ref]}]", }, - ["PreviousPage"]={ - ["cs"]="PredchoziStrana", - ["de"]="VorigeSeite", - ["en"]="PreviousPage", - ["fr"]="PagePrecedente", - ["it"]="PaginaPrecedente", - ["nl"]="VorigePagina", - ["pe"]="صفحه‌قبلی", - ["ro"]="PaginaPrecedenta", + ["cd:dimension"]={ + ["cs"]="Dimension", + ["de"]="Dimension", + ["en"]="dimension", + ["fr"]="dimension", + ["it"]="Dimension", + ["nl"]="maat", + ["ro"]="Dimension", }, - ["PrintDocument"]={ - ["cs"]="VytisknoutDokument", - ["de"]="DruckeDokument", - ["en"]="PrintDocument", - ["fr"]="ImprimeDocument", - ["it"]="StampaDocumento", - ["nl"]="PrintDocument", - ["pe"]="چاپ‌نوشتار", - ["ro"]="TiparesteDocument", + ["cd:displaymath"]={ + ["cs"]="formula", + ["de"]="formula", + ["en"]="formula", + ["fr"]="affichemath", + ["it"]="formula", + ["nl"]="formule", + ["ro"]="formula", }, - ["Query"]={ - ["cs"]="Query", - ["de"]="Query", - ["en"]="Query", - ["fr"]="Query", - ["it"]="Richiesta", - ["nl"]="RaadpleegDocument", - ["pe"]="پرسش", - ["ro"]="Query", + ["cd:displaymath-l"]={ + ["en"]="$$...$$", }, - ["QueryAgain"]={ - ["cs"]="QueryAgain", - ["de"]="QueryAgain", - ["en"]="QueryAgain", - ["fr"]="QueryAgain", - ["it"]="RinnovaRichiesta", - ["nl"]="HerhaalRaadplegen", - ["pe"]="پرسش‌دوباره", - ["ro"]="QueryAgain", + ["cd:displaymath-s"]={ + ["en"]="$$...$$", }, - ["ResetForm"]={ - ["cs"]="ResetFormulare", - ["de"]="ZuruecksetzenFormular", - ["en"]="ResetForm", - ["fr"]="RazForm", - ["it"]="ReimpostaForm", - ["nl"]="ResetFormulier", - ["pe"]="دوباره‌نشانی‌فرم", - ["ro"]="ResetareFormular", + ["cd:else-l"]={ + ["en"]="\\else ", }, - ["ResumeMovie"]={ - ["cs"]="PokracovatFilm", - ["de"]="FortsetzenFilm", - ["en"]="ResumeMovie", - ["fr"]="ReprendFilm", - ["it"]="RiprendiFilm", - ["nl"]="HervatFilm", - ["pe"]="ادامه‌فیلم", - ["ro"]="RepornesteFilm", + ["cd:else-s"]={ + ["en"]="\\else ", }, - ["ResumeRendering"]={ - ["cs"]="ResumeRendering", - ["de"]="ResumeRendering", - ["en"]="ResumeRendering", - ["fr"]="ResumeRendering", - ["it"]="ResumeRendering", - ["nl"]="HervatRendering", - ["pe"]="ادامه‌تعبیر", - ["ro"]="ResumeRendering", + ["cd:false"]={ + ["cs"]="false", + ["de"]="false", + ["en"]="false", + ["fr"]="faux", + ["it"]="false", + ["nl"]="false", + ["ro"]="false", }, - ["ResumeSound"]={ - ["cs"]="PokracovatZvuk", - ["de"]="ResumeSound", - ["en"]="ResumeSound", - ["fr"]="ReprendSon", - ["it"]="RiprendiSuono", - ["nl"]="HervatGeluid", - ["pe"]="ادامه‌صدا", - ["ro"]="RepornesteSunet", + ["cd:fi-l"]={ + ["en"]="\\fi ", }, - ["Romannumerals"]={ - ["cs"]="Rimskecislice", - ["de"]="Roemischezahlen", - ["en"]="Romannumerals", - ["fr"]="Chiffresromains", - ["it"]="Numeriromani", - ["nl"]="Romeins", - ["pe"]="اعداد‌بزرگ‌لاتین", - ["ro"]="Numereromane", + ["cd:fi-s"]={ + ["en"]="\\fi ", }, - ["SaveDocument"]={ - ["cs"]="UlozitDokument", - ["de"]="SpeichereDokument", - ["en"]="SaveDocument", - ["fr"]="SauvegardeDocument", - ["it"]="SalvaDocumento", - ["nl"]="BewaarDocument", - ["pe"]="ذخیره‌نوشتار", - ["ro"]="SalvareDocument", + ["cd:file"]={ + ["cs"]="file", + ["de"]="file", + ["en"]="file", + ["fr"]="fichier", + ["it"]="file", + ["nl"]="file", + ["ro"]="file", }, - ["SaveForm"]={ - ["cs"]="UlozitFormular", - ["de"]="SpeicheFormular", - ["en"]="SaveForm", - ["fr"]="SauvegardeForm", - ["it"]="SalvaForm", - ["nl"]="BewaarFormulier", - ["pe"]="ذخیره‌فرم", - ["ro"]="SalveazaFormular", + ["cd:file-l"]={ + ["en"]=" ... ", }, - ["SaveNamedDocument"]={ - ["cs"]="SaveNamedDocument", - ["de"]="SaveNamedDocument", - ["en"]="SaveNamedDocument", - ["fr"]="SauvegardeDocumentNomme", - ["it"]="SaveNamedDocument", - ["nl"]="BewaarDocumentOpNaam", - ["pe"]="ذخیره‌نوشتار‌بانام", - ["ro"]="SaveNamedDocument", + ["cd:file-s"]={ + ["en"]=" ... ", }, - ["SearchAgain"]={ - ["cs"]="HledatZnovu", - ["de"]="WeiterSuchen", - ["en"]="SearchAgain", - ["fr"]="RechercheSuivant", - ["it"]="CercaAncora", - ["nl"]="HerhaalZoeken", - ["pe"]="جستجوی‌دوباره", - ["ro"]="CautaDinNou", + ["cd:first"]={ + ["cs"]="first", + ["de"]="first", + ["en"]="first", + ["fr"]="premier", + ["it"]="first", + ["nl"]="eerste", + ["ro"]="first", }, - ["SearchDocument"]={ - ["cs"]="ProhledatDokument", - ["de"]="DokumentDurchsuchen", - ["en"]="SearchDocument", - ["fr"]="RechercheDocument", - ["it"]="CercaDocumento", - ["nl"]="DoorzoekDocument", - ["pe"]="جستجوی‌نوشتار", - ["ro"]="CautaDocument", + ["cd:font"]={ + ["cs"]="font", + ["de"]="font", + ["en"]="font", + ["fr"]="police", + ["it"]="font", + ["nl"]="font", + ["ro"]="font", }, - ["ShowBookmarks"]={ - ["cs"]="UkazZalozky", - ["de"]="ShowBookmarks", - ["en"]="ShowBookmarks", - ["fr"]="ShowBookmarks", - ["it"]="MostraSegnalibro", - ["nl"]="ShowBookmarks", - ["pe"]="نمایش‌چوبخط", - ["ro"]="ShowBookmarks", + ["cd:formula"]={ + ["cs"]="Formel", + ["de"]="Formel", + ["en"]="formula", + ["fr"]="formule", + ["it"]="Formel", + ["nl"]="formule", + ["ro"]="Formel", }, - ["ShowField"]={ - ["cs"]="UkazPole", - ["de"]="ZeigeFeld", - ["en"]="ShowField", - ["fr"]="MontreChamp", - ["it"]="MostraCampo", - ["nl"]="ToonVeld", - ["pe"]="نمایش‌میدان", - ["ro"]="AfiseazaCamp", + ["cd:identifier"]={ + ["cs"]="Name", + ["de"]="Name", + ["en"]="identifier", + ["fr"]="identifiant", + ["it"]="Name", + ["nl"]="naam", + ["ro"]="Name", }, - ["ShowThumbs"]={ - ["cs"]="UkazNahledy", - ["de"]="ShowThumbs", - ["en"]="ShowThumbs", - ["fr"]="ShowThumbs", - ["it"]="MostraThumbs", - ["nl"]="ShowThumbs", - ["pe"]="نمایش‌شصت", - ["ro"]="ShowThumbs", + ["cd:if-l"]={ + ["en"]="\\if... ", }, - ["StartMovie"]={ - ["cs"]="SpustitFilm", - ["de"]="StartFilm", - ["en"]="StartMovie", - ["fr"]="DemarreFilm", - ["it"]="IniziaFilm", - ["nl"]="StartFilm", - ["pe"]="شروع‌فیلم", - ["ro"]="StartFilm", + ["cd:if-s"]={ + ["en"]="\\if... ", }, - ["StartRendering"]={ - ["cs"]="StartRendering", - ["de"]="StartRendering", - ["en"]="StartRendering", - ["fr"]="StartRendering", - ["it"]="StartRendering", - ["nl"]="StartRendering", - ["pe"]="شروع‌تعبیر", - ["ro"]="StartRendering", + ["cd:index"]={ + ["cs"]="entry", + ["de"]="entry", + ["en"]="entry", + ["fr"]="index", + ["it"]="entry", + ["nl"]="ingang", + ["ro"]="entry", }, - ["StartSound"]={ - ["cs"]="StartZvuk", - ["de"]="StartSound", - ["en"]="StartSound", - ["fr"]="DemarreSon", - ["it"]="IniziaSuono", - ["nl"]="StartGeluid", - ["pe"]="شروع‌صدا", - ["ro"]="StartSunet", + ["cd:index-l"]={ + ["en"]="{..+...+..}", }, - ["StopMovie"]={ - ["cs"]="ZastavitFilm", - ["de"]="StopFilm", - ["en"]="StopMovie", - ["fr"]="StoppeFilm", - ["it"]="FermaFilm", - ["nl"]="StopFilm", - ["pe"]="پایان‌فیلم", - ["ro"]="StopFilm", + ["cd:index-s"]={ + ["en"]="{...}", }, - ["StopRendering"]={ - ["cs"]="StopRendering", - ["de"]="StopRendering", - ["en"]="StopRendering", - ["fr"]="StopRendering", - ["it"]="StopRendering", - ["nl"]="StopRendering", - ["pe"]="پایان‌تعبیر", - ["ro"]="StopRendering", + ["cd:inherits"]={ + ["cs"]="inherits", + ["de"]="inherits", + ["en"]="inherits", + ["fr"]="heritede", + ["it"]="inherits", + ["nl"]="erft", + ["ro"]="inherits", }, - ["StopSound"]={ - ["cs"]="StopZvuk", - ["de"]="StopSound", - ["en"]="StopSound", - ["fr"]="StoppeSon", - ["it"]="FermaSuono", - ["nl"]="StopGeluid", - ["pe"]="پایان‌صدا", - ["ro"]="StopSunet", + ["cd:inlinemath-l"]={ + ["en"]="$...$", }, - ["SubmitForm"]={ - ["cs"]="PoslatFormular", - ["de"]="VersendeFormular", - ["en"]="SubmitForm", - ["fr"]="SoumettreForm", - ["it"]="MandaForm", - ["nl"]="VerzendFormulier", - ["pe"]="تسلیم‌فرم", - ["ro"]="TrimiteFormular", + ["cd:inlinemath-s"]={ + ["en"]="$...$", }, - ["ToggleLayer"]={ - ["cs"]="ToggleLayer", - ["de"]="ToggleLayer", - ["en"]="ToggleLayer", - ["fr"]="ToggleLayer", - ["it"]="ToggleLayer", - ["nl"]="WisselLaag", - ["pe"]="تغییرلایه", - ["ro"]="ToggleLayer", + ["cd:key"]={ + ["cs"]="key", + ["de"]="key", + ["en"]="key", + ["fr"]="cle", + ["it"]="key", + ["nl"]="parameter", + ["ro"]="key", }, - ["ToggleViewer"]={ - ["cs"]="ZmenitProhlizec", - ["de"]="WechseleViewer", - ["en"]="ToggleViewer", - ["fr"]="ChangeVisualisateur", - ["it"]="ScambiaVisualizzatore", - ["nl"]="WisselViewer", - ["pe"]="تغییرنمایشگر", - ["ro"]="SchimbaVizualizator", + ["cd:language"]={ + ["cs"]="sprache", + ["de"]="sprache", + ["en"]="language", + ["fr"]="langage", + ["it"]="sprache", + ["nl"]="taal", + ["ro"]="sprache", }, - ["URL"]={ - ["cs"]="URL", - ["de"]="URL", - ["en"]="URL", - ["fr"]="URL", - ["it"]="URL", - ["nl"]="URL", - ["pe"]="URL", - ["ro"]="URL", + ["cd:last"]={ + ["cs"]="last", + ["de"]="last", + ["en"]="last", + ["fr"]="dernier", + ["it"]="last", + ["nl"]="laatste", + ["ro"]="last", }, - ["VideLayer"]={ - ["cs"]="VideLayer", - ["de"]="VideLayer", - ["en"]="VideLayer", - ["fr"]="VideLayer", - ["it"]="VideLayer", - ["nl"]="ToonLaag", - ["pe"]="VideLayer", - ["ro"]="VideLayer", + ["cd:list"]={ + ["cs"]="Liste", + ["de"]="Liste", + ["en"]="list", + ["fr"]="liste", + ["it"]="Liste", + ["nl"]="lijst", + ["ro"]="Liste", }, - ["ViewerHelp"]={ - ["cs"]="NapovedaProhlizece", - ["de"]="ViewerHilfe", - ["en"]="ViewerHelp", - ["fr"]="AideVisualisateur", - ["it"]="AiutoVisualizzatore", - ["nl"]="ViewerHelp", - ["pe"]="کمک‌نمایشگر", - ["ro"]="AjutorVizualizator", + ["cd:lpath"]={ + ["cs"]="lpath", + ["de"]="lpath", + ["en"]="lpath", + ["fr"]="cheminl", + ["it"]="lpath", + ["nl"]="lpath", + ["ro"]="lpath", }, - ["WEEKDAY"]={ - ["cs"]="VSEDNIDEN", - ["de"]="WOCHENTAG", - ["en"]="WEEKDAY", - ["fr"]="JOURSEMAINE", - ["it"]="GIORNOSETTIMANA", - ["nl"]="WEEKDAG", - ["pe"]="روزهفته", - ["ro"]="ZISAPTAMANA", + ["cd:luafunction"]={ + ["cs"]="luafunction", + ["de"]="luafunction", + ["en"]="luafunction", + ["fr"]="fonctionlua", + ["it"]="luafunction", + ["nl"]="luafunction", + ["ro"]="luafunction", }, - ["WORD"]={ - ["cs"]="SLOVO", - ["de"]="WORT", - ["en"]="WORD", - ["fr"]="MOT", - ["it"]="PAROLA", - ["nl"]="WOORD", - ["pe"]="کلمه", - ["ro"]="CUVANT", + ["cd:macro-l"]={ + ["en"]="\\... ", }, - ["WORDS"]={ - ["cs"]="SLOVA", - ["de"]="WOERTER", - ["en"]="WORDS", - ["fr"]="MOTS", - ["it"]="PAROLE", - ["nl"]="WOORDEN", - ["pe"]="WORDS", - ["ro"]="CUVINTE", + ["cd:macro-s"]={ + ["en"]="\\... ", }, - ["Word"]={ - ["cs"]="Slovo", - ["de"]="Wort", - ["en"]="Word", - ["fr"]="Mot", - ["it"]="Parola", - ["nl"]="Woord", - ["pe"]="Word", - ["ro"]="Cuvant", + ["cd:mark"]={ + ["cs"]="Beschriftung", + ["de"]="Beschriftung", + ["en"]="mark", + ["fr"]="marque", + ["it"]="Beschriftung", + ["nl"]="markering", + ["ro"]="Beschriftung", }, - ["Words"]={ - ["cs"]="Slova", - ["de"]="Woerter", - ["en"]="Words", - ["fr"]="Mots", - ["it"]="Parole", - ["nl"]="Woorden", - ["pe"]="Words", - ["ro"]="Cuvinte", + ["cd:marking"]={ + ["cs"]="marking", + ["de"]="marking", + ["en"]="marking", + ["fr"]="marquage", + ["it"]="marking", + ["nl"]="markering", + ["ro"]="marking", }, - ["abbreviation"]={ - ["cs"]="zkratka", - ["de"]="abkuerzung", - ["en"]="abbreviation", - ["fr"]="abreviation", - ["it"]="abbreviazione", - ["nl"]="afkorting", - ["pe"]="اختصار", - ["ro"]="abreviere", + ["cd:math"]={ + ["cs"]="formula", + ["de"]="formula", + ["en"]="formula", + ["fr"]="math", + ["it"]="formula", + ["nl"]="formule", + ["ro"]="formula", }, - ["abbreviations"]={ - ["cs"]="zkratky", - ["de"]="abkuerzungen", - ["en"]="abbreviations", - ["fr"]="abreviations", - ["it"]="abbreviazioni", - ["nl"]="afkortingen", - ["pe"]="اختصارات", - ["ro"]="abrevieri", + ["cd:math-l"]={ + ["en"]="$...$", }, - ["absolute"]={ - ["cs"]="absolutni", - ["de"]="absolut", - ["en"]="absolute", - ["fr"]="absolute", - ["it"]="assoluto", - ["nl"]="absoluut", - ["pe"]="قطعی", - ["ro"]="absolut", + ["cd:math-s"]={ + ["en"]="$...$", }, - ["anchor"]={ - ["en"]="anchor", - ["nl"]="anker", + ["cd:matrix"]={ + ["cs"]="n*m", + ["de"]="n*m", + ["en"]="n*m", + ["fr"]="matrice", + ["it"]="n*m", + ["nl"]="n*m", + ["ro"]="n*m", }, - ["action"]={ - ["cs"]="akce", - ["de"]="aktion", - ["en"]="action", - ["fr"]="action", - ["it"]="azione", - ["nl"]="actie", - ["pe"]="کنش", - ["ro"]="actiune", + ["cd:name"]={ + ["cs"]="Name", + ["de"]="Name", + ["en"]="name", + ["fr"]="nom", + ["it"]="Name", + ["nl"]="naam", + ["ro"]="Name", }, - ["after"]={ - ["cs"]="po", - ["de"]="nach", - ["en"]="after", - ["fr"]="apres", - ["it"]="dopo", - ["nl"]="na", - ["pe"]="بعداز", - ["ro"]="dupa", + ["cd:noargument-l"]={ + ["en"]="\\...", }, - ["all"]={ - ["cs"]="vse", - ["de"]="alles", - ["en"]="all", - ["fr"]="tout", - ["it"]="tutti", - ["nl"]="alles", - ["pe"]="همه", - ["ro"]="tot", + ["cd:noargument-s"]={ + ["en"]="\\...", }, - ["alphabetic"]={ - ["en"]="alphabetic", + ["cd:node"]={ + ["cs"]="node", + ["de"]="node", + ["en"]="node", + ["fr"]="noeud", + ["it"]="node", + ["nl"]="node", + ["ro"]="node", }, - ["always"]={ - ["cs"]="vzdy", - ["de"]="immer", - ["en"]="always", - ["fr"]="toujours", - ["it"]="sempre", - ["nl"]="altijd", - ["pe"]="همواره", - ["ro"]="totdeauna", + ["cd:none-l"]={ + ["en"]=".. ... ..", }, - ["and"]={ - ["de"]="und", - ["en"]="and", - ["nl"]="en", + ["cd:none-s"]={ + ["en"]="...", }, - ["answerarea"]={ - ["cs"]="answerarea", - ["de"]="answerarea", - ["en"]="answerarea", - ["fr"]="answerarea", - ["it"]="answerarea", - ["nl"]="antwoordgebied", - ["pe"]="answerarea", - ["ro"]="answerarea", + ["cd:nothing"]={ + ["cs"]="empty", + ["de"]="empty", + ["en"]="empty", + ["fr"]="rien", + ["it"]="empty", + ["nl"]="leeg", + ["ro"]="empty", }, - ["appendices"]={ - ["cs"]="dodatky", - ["de"]="anhaenge", - ["en"]="appendices", - ["fr"]="annexes", - ["it"]="appendici", - ["nl"]="bijlagen", - ["pe"]="پیوستها", - ["ro"]="apendixuri", + ["cd:nothing-l"]={ + ["en"]="...", }, - ["appendix"]={ - ["cs"]="dodatek", - ["de"]="anhang", - ["en"]="appendix", - ["fr"]="annexe", - ["it"]="appendice", - ["nl"]="bijlage", - ["pe"]="پیوست", - ["ro"]="apendix", + ["cd:nothing-s"]={ + ["en"]="...", }, - ["april"]={ - ["cs"]="duben", - ["de"]="april", - ["en"]="april", - ["fr"]="avril", - ["it"]="aprile", - ["nl"]="april", - ["pe"]="آوریل", - ["ro"]="aprilie", + ["cd:number"]={ + ["cs"]="Nummer", + ["de"]="Nummer", + ["en"]="number", + ["fr"]="nombre", + ["it"]="Nummer", + ["nl"]="getal", + ["ro"]="Nummer", }, - ["atleftmargin"]={ - ["cs"]="atleftmargin", - ["de"]="atleftmargin", - ["en"]="atleftmargin", - ["fr"]="atleftmargin", - ["it"]="atleftmargin", - ["nl"]="oplinkermarge", - ["pe"]="درحاشیه‌چپ", - ["ro"]="atleftmargin", + ["cd:oneargument"]={ + ["en"]="\\...#1", }, - ["atmargin"]={ - ["cs"]="naokraji", - ["de"]="amrand", - ["en"]="atmargin", - ["fr"]="alamarge", - ["it"]="almargine", - ["nl"]="opmarge", - ["pe"]="درحاشیه", - ["ro"]="lamargine", + ["cd:optional"]={ + ["cs"]="opt", + ["de"]="opt", + ["en"]="opt", + ["fr"]="optionnel", + ["it"]="opt", + ["nl"]="opt", + ["ro"]="opt", }, - ["atpage"]={ - ["cs"]="nastrance", - ["de"]="aufseite", - ["en"]="atpage", - ["fr"]="alapage", - ["it"]="apagina", - ["nl"]="oppagina", - ["pe"]="درصفحه", - ["ro"]="lapagina", + ["cd:or-l"]={ + ["en"]="\\or ", }, - ["atrightmargin"]={ - ["cs"]="atrightmargin", - ["de"]="atrightmargin", - ["en"]="atrightmargin", - ["fr"]="atrightmargin", - ["it"]="atrightmargin", - ["nl"]="oprechtermarge", - ["pe"]="درحاشیه‌راست", - ["ro"]="atrightmargin", + ["cd:or-s"]={ + ["en"]="\\or ", }, - ["attachment"]={ - ["en"]="attachment", - ["nl"]="aanhangsel", + ["cd:par-l"]={ + ["en"]="\\par ", }, - ["august"]={ - ["cs"]="srpen", - ["de"]="august", - ["en"]="august", - ["fr"]="août", - ["it"]="agosto", - ["nl"]="augustus", - ["pe"]="آگوست", - ["ro"]="august", + ["cd:par-s"]={ + ["en"]="\\par ", }, - ["author"]={ - ["cs"]="autor", - ["de"]="autor", - ["en"]="author", - ["fr"]="auteur", - ["it"]="autore", - ["nl"]="auteur", - ["ro"]="autor", + ["cd:parenthesis-l"]={ + ["en"]="(...,...)", }, - ["auto"]={ - ["cs"]="auto", - ["de"]="auto", - ["en"]="auto", - ["fr"]="auto", - ["it"]="auto", - ["nl"]="auto", - ["pe"]="خودکار", - ["ro"]="auto", + ["cd:parenthesis-s"]={ + ["en"]="(...)", }, - ["autointro"]={ - ["cs"]="autouvod", - ["de"]="autointro", - ["en"]="autointro", - ["fr"]="autointro", - ["it"]="autointro", - ["nl"]="autointro", - ["pe"]="پیشگفتارخودکار", - ["ro"]="autointro", + ["cd:path"]={ + ["cs"]="path", + ["de"]="path", + ["en"]="path", + ["fr"]="chemin", + ["it"]="path", + ["nl"]="path", + ["ro"]="path", }, - ["autopunctuation"]={ - ["en"]="autopunctuation", + ["cd:plural"]={ + ["cs"]="plural", + ["de"]="plural", + ["en"]="plural", + ["fr"]="pluriel", + ["it"]="plural", + ["nl"]="naam", + ["ro"]="plural", }, - ["back"]={ - ["cs"]="zpet", - ["de"]="zurueck", - ["en"]="back", - ["fr"]="retour", - ["it"]="dietro", - ["nl"]="terug", - ["pe"]="پشت", - ["ro"]="inapot", + ["cd:position"]={ + ["cs"]="position", + ["de"]="position", + ["en"]="position", + ["fr"]="position", + ["it"]="position", + ["nl"]="positie", + ["ro"]="position", }, - ["background"]={ - ["cs"]="pozadi", - ["de"]="hintergrund", - ["en"]="background", - ["fr"]="arriereplan", - ["it"]="sfondo", - ["nl"]="achtergrond", - ["pe"]="پس‌زمینه", - ["ro"]="fundal", + ["cd:position-l"]={ + ["en"]="(...,...)", }, - ["backmatter"]={ - ["cs"]="epilogy", - ["de"]="epiloge", - ["en"]="backmatter", - ["fr"]="epilogue", - ["it"]="postambolo", - ["nl"]="uitleidingen", - ["pe"]="پس‌مطلب", - ["ro"]="epilogul", + ["cd:position-s"]={ + ["en"]="(...)", }, - ["backpart"]={ - ["cs"]="epilog", - ["de"]="epilog", - ["en"]="backpart", - ["fr"]="postface", - ["it"]="postfazione", - ["nl"]="uitleiding", - ["pe"]="پس‌قسمت", - ["ro"]="epilog", + ["cd:processor"]={ + ["cs"]="processor", + ["de"]="processor", + ["en"]="processor", + ["fr"]="processeur", + ["it"]="processor", + ["nl"]="verwerker", + ["ro"]="processor", }, - ["backspace"]={ - ["cs"]="zpetnamezera", - ["de"]="rumpfspatium", - ["en"]="backspace", - ["fr"]="retourarriere", - ["it"]="backspace", - ["nl"]="rugwit", - ["pe"]="فضای‌پشت", - ["ro"]="spatiuspate", + ["cd:reference"]={ + ["cs"]="reference", + ["de"]="reference", + ["en"]="reference", + ["fr"]="reference", + ["it"]="reference", + ["nl"]="verwijzing", + ["ro"]="reference", }, - ["backward"]={ - ["cs"]="zpet", - ["de"]="rueckwaerts", - ["en"]="backward", - ["fr"]="retourarriere", - ["it"]="indietro", - ["nl"]="achteruit", - ["pe"]="عقب‌گرد", - ["ro"]="inapoi", + ["cd:reference-l"]={ + ["en"]="[...,...]", + ["lua"]="{..., ...}", }, - ["bbl"]={ - ["en"]="bbl", + ["cd:reference-s"]={ + ["en"]="[...]", + ["lua"]="{ ... }", }, - ["before"]={ - ["cs"]="pred", - ["de"]="vor", - ["en"]="before", - ["fr"]="avant", - ["it"]="prima", - ["nl"]="voor", - ["pe"]="قبل‌از", - ["ro"]="inainte", + ["cd:row"]={ + ["cs"]="row", + ["de"]="row", + ["en"]="row", + ["fr"]="rang", + ["it"]="row", + ["nl"]="rij", + ["ro"]="row", }, - ["begin"]={ - ["en"]="begin", - ["nl"]="begin", + ["cd:section"]={ + ["cs"]="Abschnitt", + ["de"]="Abschnitt", + ["en"]="section", + ["fr"]="section", + ["it"]="Abschnitt", + ["nl"]="sectie", + ["ro"]="Abschnitt", }, - ["bib"]={ - ["en"]="bib", + ["cd:sectionblock"]={ + ["cs"]="sectionblock", + ["de"]="sectionblock", + ["en"]="sectionblock", + ["fr"]="blocsection", + ["it"]="sectionblock", + ["nl"]="sectieblok", + ["ro"]="sectionblock", }, - ["big"]={ - ["cs"]="velke", - ["de"]="gross", - ["en"]="big", - ["fr"]="grand", - ["it"]="grande", - ["nl"]="groot", - ["pe"]="بزرگ", - ["ro"]="mare", + ["cd:see"]={ + ["cs"]="siehe", + ["de"]="siehe", + ["en"]="see", + ["fr"]="voir", + ["it"]="siehe", + ["nl"]="zie", + ["ro"]="siehe", }, - ["bigbodyfont"]={ - ["cs"]="bigbodyfont", - ["de"]="bigbodyfont", - ["en"]="bigbodyfont", - ["fr"]="grandepolicecorp", - ["it"]="grossofontdeltesto", - ["nl"]="grootkorps", - ["pe"]="قلم‌بدنه‌بزرگ", - ["ro"]="bigbodyfont", + ["cd:sep-l"]={ + ["en"]="\\", }, - ["bigger"]={ - ["en"]="bigger", - ["nl"]="groter", + ["cd:sep-s"]={ + ["en"]="\\", }, - ["bigpreference"]={ - ["cs"]="vysokapriorita", - ["de"]="grosszuegig", - ["en"]="bigpreference", - ["fr"]="grandepreference", - ["it"]="grandepreferenza", - ["nl"]="grotevoorkeur", - ["pe"]="اولویت‌بزرگ", - ["ro"]="preferintamare", + ["cd:setup"]={ + ["cs"]="setup", + ["de"]="setup", + ["en"]="setup", + ["fr"]="configurer", + ["it"]="setup", + ["nl"]="setup", + ["ro"]="setup", }, - ["blank"]={ - ["cs"]="prazdny", - ["de"]="blanko", - ["en"]="blank", - ["fr"]="vide", - ["it"]="rigovuoto", - ["nl"]="blanko", - ["pe"]="خالی", - ["ro"]="blank", - }, - ["block"]={ - ["en"]="block", + ["cd:sign"]={ + ["en"]="[-+]", }, - ["blockquote"]={ - ["cs"]="blockquote", - ["de"]="blockquote", - ["en"]="blockquote", - ["fr"]="blockquote", - ["it"]="blockquote", - ["nl"]="blokcitaat", - ["pe"]="نقل‌بلوک", - ["ro"]="blockquote", + ["cd:singular"]={ + ["cs"]="singular", + ["de"]="singular", + ["en"]="singular", + ["fr"]="singulier", + ["it"]="singular", + ["nl"]="naam", + ["ro"]="singular", }, - ["bodymatter"]={ - ["cs"]="hlavnicasti", - ["de"]="haupttexte", - ["en"]="bodymatter", - ["fr"]="texteprincipal", - ["it"]="testiprincipali", - ["nl"]="hoofdteksten", - ["pe"]="مطلب‌بدنه", - ["ro"]="principalul", + ["cd:style"]={ + ["cs"]="style", + ["de"]="style", + ["en"]="style", + ["fr"]="style", + ["it"]="style", + ["nl"]="letter", + ["ro"]="style", }, - ["bodypart"]={ - ["cs"]="hlavnicast", - ["de"]="haupttext", - ["en"]="bodypart", - ["fr"]="corpsdetexte", - ["it"]="testoprincipale", - ["nl"]="hoofdtekst", - ["pe"]="قسمت‌بدنه", - ["ro"]="principal", + ["cd:template"]={ + ["cs"]="template", + ["de"]="template", + ["en"]="template", + ["fr"]="gabarit", + ["it"]="template", + ["nl"]="sjabloon", + ["ro"]="template", }, - ["bold"]={ - ["cs"]="tucne", - ["de"]="fett", - ["en"]="bold", - ["fr"]="gras", - ["it"]="grassetto", - ["nl"]="vet", - ["pe"]="مشکی", - ["ro"]="aldin", + ["cd:template-l"]={ + ["en"]="[|...|...|]", }, - ["bolditalic"]={ - ["cs"]="tucnekurzivni", - ["de"]="fettitalic", - ["en"]="bolditalic", - ["fr"]="italiquegras", - ["it"]="grassettocorsivo", - ["nl"]="vetitalic", - ["pe"]="ایتالیک‌مشکی", - ["ro"]="aldinitalic", + ["cd:template-s"]={ + ["en"]="[|...|]", }, - ["boldslanted"]={ - ["cs"]="tucnesklonene", - ["de"]="fettgeneigt", - ["en"]="boldslanted", - ["fr"]="inclinegras", - ["it"]="grassettoinclinato", - ["nl"]="vetschuin", - ["pe"]="خوابیده‌مشکی", - ["ro"]="aldininclinat", + ["cd:text"]={ + ["cs"]="Text", + ["de"]="Text", + ["en"]="text", + ["fr"]="texte", + ["it"]="Text", + ["nl"]="tekst", + ["ro"]="Text", }, - ["bookmark"]={ - ["cs"]="zalozka", - ["de"]="bookmark", - ["en"]="bookmark", - ["fr"]="marquepage", - ["it"]="segnalibro", - ["nl"]="bookmark", - ["pe"]="چوبخط", - ["ro"]="semncarte", + ["cd:textual-l"]={ + ["en"]=".. ... ..", }, - ["both"]={ - ["cs"]="obe", - ["de"]="beide", - ["en"]="both", - ["fr"]="lesdeux", - ["it"]="entrambi", - ["nl"]="beide", - ["pe"]="هردو", - ["ro"]="ambele", + ["cd:textual-s"]={ + ["en"]="...", }, - ["bothtext"]={ - ["en"]="bothtext", + ["cd:threearguments"]={ + ["en"]="\\...#1#2#3", }, - ["bottom"]={ - ["cs"]="spodek", - ["de"]="unten", - ["en"]="bottom", - ["fr"]="inf", - ["it"]="fondo", - ["nl"]="onder", - ["pe"]="پایین", - ["ro"]="subsol", + ["cd:threewords-l"]={ + ["en"]="[..+..+..]", }, - ["box"]={ - ["en"]="box", + ["cd:threewords-s"]={ + ["en"]="[..+..+..]", }, - ["brief"]={ - ["cs"]="brief", - ["de"]="brief", - ["en"]="brief", - ["fr"]="brief", - ["it"]="brief", - ["nl"]="brief", - ["pe"]="مختصر", - ["ro"]="brief", + ["cd:title"]={ + ["cs"]="Setup", + ["de"]="Setup", + ["en"]="setup", + ["fr"]="titre", + ["it"]="Setup", + ["nl"]="setup", + ["ro"]="Setup", }, - ["broad"]={ - ["cs"]="siroky", - ["de"]="breit", - ["en"]="broad", - ["fr"]="large", - ["it"]="ampio", - ["nl"]="ruim", - ["pe"]="گسترده", - ["ro"]="broad", + ["cd:to-l"]={ + ["en"]="\\to ", }, - ["buffer"]={ - ["cs"]="buffer", - ["de"]="puffer", - ["en"]="buffer", - ["fr"]="buffer", - ["it"]="buffer", - ["nl"]="buffer", - ["pe"]="بافر", - ["ro"]="buffer", + ["cd:to-s"]={ + ["en"]="\\to ", }, - ["by"]={ - ["cs"]="skrz", - ["de"]="pro", - ["en"]="by", - ["fr"]="par", - ["it"]="da", - ["nl"]="per", - ["pe"]="بوسیله", - ["ro"]="de", + ["cd:triplet"]={ + ["cs"]="triplet", + ["de"]="triplet", + ["en"]="triplet", + ["fr"]="triplet", + ["it"]="triplet", + ["nl"]="triplet", + ["ro"]="triplet", }, - ["calligraphic"]={ - ["cs"]="kaligraficke", - ["de"]="kalligraphie", - ["en"]="calligraphic", - ["fr"]="calligraphique", - ["it"]="calligrafico", - ["nl"]="calligrafie", - ["pe"]="خوشنویسی", - ["ro"]="caligrafic", + ["cd:triplet-l"]={ + ["en"]="[x:y:z,..]", }, - ["camel"]={ - ["en"]="camel", + ["cd:triplet-s"]={ + ["en"]="[x:y:z]", }, - ["cap"]={ - ["cs"]="kap", - ["de"]="kap", - ["en"]="cap", - ["fr"]="cap", - ["it"]="cap", - ["nl"]="kap", - ["pe"]="cap", - ["ro"]="cap", + ["cd:true"]={ + ["cs"]="true", + ["de"]="true", + ["en"]="true", + ["fr"]="vrai", + ["it"]="true", + ["nl"]="true", + ["ro"]="true", }, - ["capital"]={ - ["cs"]="kapitalky", - ["de"]="versalien", - ["en"]="capital", - ["fr"]="capitale", - ["it"]="maiuscolo", - ["nl"]="kapitaal", - ["pe"]="capital", - ["ro"]="majuscula", + ["cd:twoarguments"]={ + ["en"]="\\...#1#2", }, - ["center"]={ - ["cs"]="center", - ["de"]="center", - ["en"]="center", - ["fr"]="center", - ["it"]="center", - ["nl"]="centreer", - ["pe"]="مرکز", - ["ro"]="center", + ["cd:twowords-l"]={ + ["en"]="[..+..]", }, - ["centerlast"]={ - ["en"]="centerlast", + ["cd:twowords-s"]={ + ["en"]="[..+..]", }, - ["chapter"]={ - ["cs"]="kapitola", - ["de"]="kapitel", - ["en"]="chapter", - ["fr"]="chapitre", - ["it"]="capitolo", - ["nl"]="hoofdstuk", - ["pe"]="فصل", - ["ro"]="capitol", + ["cd:url"]={ + ["cs"]="url", + ["de"]="url", + ["en"]="url", + ["fr"]="url", + ["it"]="url", + ["nl"]="url", + ["ro"]="url", }, - ["character"]={ - ["cs"]="pismeno", - ["de"]="buchstabe", - ["en"]="character", - ["fr"]="caractere", - ["it"]="lettera", - ["nl"]="letter", - ["pe"]="حرف", - ["ro"]="caracter", + ["cd:userdata"]={ + ["cs"]="userdata", + ["de"]="userdata", + ["en"]="userdata", + ["fr"]="donneesutilisateur", + ["it"]="userdata", + ["nl"]="gebruikersdata", + ["ro"]="userdata", }, - ["characters"]={ - ["cs"]="pismena", - ["de"]="buchstaben", - ["en"]="characters", - ["fr"]="caracteres", - ["it"]="lettere", - ["nl"]="letters", - ["pe"]="حرفها", - ["ro"]="caractere", - }, - ["chemical"]={ - ["en"]="chemical", + ["cd:value"]={ + ["cs"]="value", + ["de"]="value", + ["en"]="value", + ["fr"]="valeur", + ["it"]="value", + ["nl"]="waarde", + ["ro"]="value", }, - ["chemicals"]={ - ["en"]="chemicals", + ["cd:word"]={ + ["cs"]="word", + ["de"]="word", + ["en"]="word", + ["fr"]="mot", + ["it"]="word", + ["nl"]="woord", + ["ro"]="word", }, - ["chemistry"]={ - ["en"]="chemistry", - ["nl"]="chemie", + ["cd:word-l"]={ + ["en"]="{.. ... ..}", + ["lua"]="\".. ... ..\"", }, - ["cite"]={ - ["en"]="cite", + ["cd:word-s"]={ + ["en"]="{...}", + ["lua"]="\"...\"", }, - ["closed"]={ - ["en"]="closed", - ["nl"]="gesloten", + ["cd:xmlsetup"]={ + ["cs"]="xmlsetup", + ["de"]="xmlsetup", + ["en"]="xmlsetup", + ["fr"]="configurationxml", + ["it"]="xmlsetup", + ["nl"]="xmlsetup", + ["ro"]="xmlsetup", }, - ["color"]={ - ["cs"]="barevne", - ["de"]="farbe", - ["en"]="color", - ["fr"]="couleur", - ["it"]="colore", - ["nl"]="kleur", - ["pe"]="رنگ", - ["ro"]="culoare", + }, + ["variables"]={ + ["Addition"]={ + ["cs"]="Pridavek", + ["de"]="Zusatz", + ["en"]="Addition", + ["fr"]="Ajout", + ["it"]="Aggiunta", + ["nl"]="Toevoeging", + ["pe"]="جمع", + ["ro"]="Adaugare", }, - ["column"]={ - ["cs"]="column", - ["de"]="column", - ["en"]="column", - ["fr"]="colonne", - ["it"]="colonna", - ["nl"]="kolom", - ["pe"]="ستون", - ["ro"]="coloana", + ["Alphabetic"]={ + ["en"]="Alphabetic", + ["fr"]="Alphabetique", }, - ["columns"]={ - ["cs"]="sloupce", - ["de"]="spalten", - ["en"]="columns", - ["fr"]="colonnes", - ["it"]="colonne", - ["nl"]="kolommen", - ["pe"]="ستونها", - ["ro"]="coloane", + ["Balloon"]={ + ["cs"]="Bublinka", + ["de"]="Ballon", + ["en"]="Balloon", + ["fr"]="Ballon", + ["it"]="Pallone", + ["nl"]="Ballon", + ["pe"]="بادکنک", + ["ro"]="Balon", }, - ["combination"]={ - ["en"]="combination", - ["nl"]="combinatie", + ["Cap"]={ + ["cs"]="Kap", + ["de"]="Kap", + ["en"]="Cap", + ["fr"]="Cap", + ["it"]="Cap", + ["nl"]="Kap", + ["pe"]="Cap", + ["ro"]="Cap", }, - ["command"]={ - ["cs"]="prikaz", - ["de"]="befehl", - ["en"]="command", - ["fr"]="commande", - ["it"]="comando", - ["nl"]="commando", - ["pe"]="فرمان", - ["ro"]="comanda", + ["Capital"]={ + ["cs"]="Kapitalky", + ["de"]="Versalien", + ["en"]="Capital", + ["fr"]="Capitales", + ["it"]="Maiuscolo", + ["nl"]="Kapitaal", + ["pe"]="Capital", + ["ro"]="Majuscula", }, - ["commands"]={ - ["cs"]="prikazy", - ["de"]="befehle", - ["en"]="commands", - ["fr"]="commandes", - ["it"]="comandi", - ["nl"]="commandos", - ["pe"]="فرمانها", - ["ro"]="comenzi", + ["Character"]={ + ["cs"]="Pismeno", + ["de"]="Buchstabe", + ["en"]="Character", + ["fr"]="Caractere", + ["it"]="Lettera", + ["nl"]="Letter", + ["pe"]="Character", + ["ro"]="Caracter", }, - ["comment"]={ - ["cs"]="komentar", - ["de"]="kommentar", - ["en"]="comment", - ["fr"]="commentaire", - ["it"]="commento", - ["nl"]="commentaar", - ["pe"]="توضیح", - ["ro"]="comentariu", + ["Characters"]={ + ["cs"]="Pismena", + ["de"]="Buchstaben", + ["en"]="Characters", + ["fr"]="Caracteres", + ["it"]="Lettere", + ["nl"]="Letters", + ["pe"]="Characters", + ["ro"]="Caractere", }, - ["component"]={ - ["cs"]="komponenta", - ["de"]="komponente", - ["en"]="component", - ["fr"]="composant", - ["it"]="componente", - ["nl"]="onderdeel", - ["pe"]="مولفه", - ["ro"]="componenta", + ["CloseDocument"]={ + ["cs"]="ZavritDokument", + ["de"]="SchliesseDokument", + ["en"]="CloseDocument", + ["fr"]="FermerDocument", + ["it"]="ChiudiDocumento", + ["nl"]="SluitDocument", + ["pe"]="بستن‌نوشتار", + ["ro"]="InchideDocument", }, - ["compressseparator"]={ - ["en"]="compressseparator", + ["ExitViewer"]={ + ["cs"]="UkoncitProhlizec", + ["de"]="BeendeViewer", + ["en"]="ExitViewer", + ["fr"]="SortirVisualisateur", + ["it"]="EsciVisualizzatore", + ["nl"]="VerlaatViewer", + ["pe"]="خروج‌نمایشگر", + ["ro"]="IesireVizualizator", }, - ["compressstopper"]={ - ["en"]="compressstopper", + ["FirstPage"]={ + ["cs"]="PrvniStrana", + ["de"]="ErsteSeite", + ["en"]="FirstPage", + ["fr"]="PremierePage", + ["it"]="PrimaPagina", + ["nl"]="EerstePagina", + ["pe"]="صفحه‌اول", + ["ro"]="PrimaPagina", }, - ["concept"]={ - ["cs"]="koncept", - ["de"]="konzept", - ["en"]="concept", - ["fr"]="concept", - ["it"]="concetto", - ["nl"]="concept", - ["pe"]="مفهوم", - ["ro"]="concept", + ["FitHeight"]={ + ["cs"]="FitHeight", + ["de"]="HoehePassend", + ["en"]="FitHeight", + ["fr"]="AdapterHauteur", + ["it"]="FitHeight", + ["nl"]="HoogtePassend", + ["pe"]="پرکردن‌ارتفاع", + ["ro"]="AjustatInaltime", }, - ["construction"]={ - ["en"]="construction", + ["FitWidth"]={ + ["cs"]="FitWidth", + ["de"]="BreitePassend", + ["en"]="FitWidth", + ["fr"]="AdapterLargeur", + ["it"]="FitWidth", + ["nl"]="BreedtePassend", + ["pe"]="پرکردن‌عرض", + ["ro"]="AjustatLatime", }, - ["content"]={ - ["cs"]="obsah", - ["de"]="inhalt", - ["en"]="content", - ["fr"]="contenu", - ["it"]="indice", - ["nl"]="inhoud", - ["pe"]="محتوا", - ["ro"]="cuprins", + ["GotoPage"]={ + ["cs"]="JdiNaStranku", + ["de"]="GotoPage", + ["en"]="GotoPage", + ["fr"]="AlleraPage", + ["it"]="VaiAPagina", + ["nl"]="GaNaarPagina", + ["pe"]="برو‌به‌صفحه", + ["ro"]="LaPagina", }, - ["contents"]={ - ["cs"]="obsah", - ["de"]="inhalte", - ["en"]="contents", - ["fr"]="contenus", - ["it"]="indici", - ["nl"]="inhouden", - ["pe"]="محتویات", - ["ro"]="cuprinsuri", + ["Greek"]={ + ["cs"]="Recky", + ["de"]="Griechisch", + ["en"]="Greek", + ["fr"]="Grec", + ["it"]="Greco", + ["nl"]="Grieks", + ["pe"]="یونانی", + ["ro"]="Grec", }, - ["continue"]={ - ["cs"]="pokracovat", - ["de"]="fortsetzten", - ["en"]="continue", - ["fr"]="continue", - ["it"]="continua", - ["nl"]="verder", - ["pe"]="ادامه", - ["ro"]="continuu", + ["Help"]={ + ["cs"]="Napoveda", + ["de"]="Hilfe", + ["en"]="Help", + ["fr"]="Aide", + ["it"]="Aiuto", + ["nl"]="Help", + ["pe"]="کمک", + ["ro"]="Ajutor", + }, + ["HideField"]={ + ["cs"]="SkryjPole", + ["de"]="VerbergeFeld", + ["en"]="HideField", + ["fr"]="CacherChamps", + ["it"]="NascondiCampo", + ["nl"]="VerbergVeld", + ["pe"]="پنهان‌میدان", + ["ro"]="AscundeCamp", + }, + ["HideLayer"]={ + ["cs"]="HideLayer", + ["de"]="HideLayer", + ["en"]="HideLayer", + ["fr"]="CacherCalque", + ["it"]="HideLayer", + ["nl"]="VerbergLaag", + ["pe"]="پنهان‌لایه", + ["ro"]="HideLayer", + }, + ["Key"]={ + ["cs"]="Klavesa", + ["de"]="Schluessel", + ["en"]="Key", + ["fr"]="Cle", + ["it"]="Tasto", + ["nl"]="Sleutel", + ["pe"]="کلید", + ["ro"]="Cheie", + }, + ["LastPage"]={ + ["cs"]="PosledniStrana", + ["de"]="LetzteSeite", + ["en"]="LastPage", + ["fr"]="DernierePage", + ["it"]="UltimaPagina", + ["nl"]="LaatstePagina", + ["pe"]="صفحه‌آخر", + ["ro"]="UltimaPagina", + }, + ["LoadForm"]={ + ["cs"]="NacistFormular", + ["de"]="LadeFormular", + ["en"]="LoadForm", + ["fr"]="ChargerFormulaire", + ["it"]="CaricaForm", + ["nl"]="LaadFormulier", + ["pe"]="بارگذاشتن‌فرم", + ["ro"]="IncarcaFormular", + }, + ["MONTH"]={ + ["cs"]="MESIC", + ["de"]="MONAT", + ["en"]="MONTH", + ["fr"]="MOIS", + ["it"]="MESE", + ["nl"]="MAAND", + ["pe"]="ماه", + ["ro"]="LUNA", + }, + ["New"]={ + ["cs"]="Novy", + ["de"]="Neu", + ["en"]="New", + ["fr"]="Nouveau", + ["it"]="Nuovo", + ["nl"]="Nieuw", + ["pe"]="جدید", + ["ro"]="Nou", + }, + ["NextJump"]={ + ["cs"]="NasledujiciSkok", + ["de"]="NaechsterSprung", + ["en"]="NextJump", + ["fr"]="SautSuivant", + ["it"]="SaltoSuccessivo", + ["nl"]="VolgendeSprong", + ["pe"]="پرش‌بعدی", + ["ro"]="SaltUrmator", + }, + ["NextPage"]={ + ["cs"]="DalsiStrana", + ["de"]="FolgendeSeite", + ["en"]="NextPage", + ["fr"]="PageSuivante", + ["it"]="PaginaSuccessiva", + ["nl"]="VolgendePagina", + ["pe"]="صفحه‌بعدی", + ["ro"]="PaginaUrmatoare", + }, + ["Numbers"]={ + ["cs"]="Cisla", + ["de"]="Ziffern", + ["en"]="Numbers", + ["fr"]="Numeros", + ["it"]="Numeri", + ["nl"]="Cijfers", + ["pe"]="شماره‌ها", + ["ro"]="Numere", + }, + ["OpenNamedDocument"]={ + ["cs"]="OpenNamedDocument", + ["de"]="OpenNamedDocument", + ["en"]="OpenNamedDocument", + ["fr"]="OuvrirDocumentNomme", + ["it"]="OpenNamedDocument", + ["nl"]="OpenDocumentOpNaam", + ["pe"]="بازکردن‌نوشتار‌ذخیره‌شده", + ["ro"]="OpenNamedDocument", + }, + ["Ordinal"]={ + ["en"]="Ordinal", + ["fr"]="Ordinal", + }, + ["Paragraph"]={ + ["cs"]="Odstavec", + ["de"]="Absatz", + ["en"]="Paragraph", + ["fr"]="Paragraphe", + ["it"]="Capoverso", + ["nl"]="Paragraaf", + ["pe"]="پاراگراف", + ["ro"]="Paragraf", + }, + ["PauseMovie"]={ + ["cs"]="PozastavitFilm", + ["de"]="PauseFilm", + ["en"]="PauseMovie", + ["fr"]="PauseFilm", + ["it"]="PausaFilm", + ["nl"]="PauzeerFilm", + ["pe"]="ایست‌فیلم", + ["ro"]="PauzaFilm", + }, + ["PauseRendering"]={ + ["cs"]="PauseRendering", + ["de"]="PauseRendering", + ["en"]="PauseRendering", + ["fr"]="PauseRendu", + ["it"]="PauseRendering", + ["nl"]="PauzeerRendering", + ["pe"]="توقف‌تعبیر", + ["ro"]="PauseRendering", + }, + ["PauseSound"]={ + ["cs"]="PozastavitZvuk", + ["de"]="PauseSound", + ["en"]="PauseSound", + ["fr"]="PauseSon", + ["it"]="PausaSuono", + ["nl"]="PauzeerGeluid", + ["pe"]="ایست‌صدا", + ["ro"]="PauzaSunet", + }, + ["PreviousJump"]={ + ["cs"]="PredchoziSkok", + ["de"]="VorigerSprung", + ["en"]="PreviousJump", + ["fr"]="SautPrecedent", + ["it"]="SaltoPrecedente", + ["nl"]="VorigeSprong", + ["pe"]="پرش‌قبلی", + ["ro"]="SaltPrecedent", + }, + ["PreviousPage"]={ + ["cs"]="PredchoziStrana", + ["de"]="VorigeSeite", + ["en"]="PreviousPage", + ["fr"]="PagePrecedente", + ["it"]="PaginaPrecedente", + ["nl"]="VorigePagina", + ["pe"]="صفحه‌قبلی", + ["ro"]="PaginaPrecedenta", + }, + ["PrintDocument"]={ + ["cs"]="VytisknoutDokument", + ["de"]="DruckeDokument", + ["en"]="PrintDocument", + ["fr"]="ImprimerDocument", + ["it"]="StampaDocumento", + ["nl"]="PrintDocument", + ["pe"]="چاپ‌نوشتار", + ["ro"]="TiparesteDocument", + }, + ["Query"]={ + ["cs"]="Query", + ["de"]="Query", + ["en"]="Query", + ["fr"]="Interroger", + ["it"]="Richiesta", + ["nl"]="RaadpleegDocument", + ["pe"]="پرسش", + ["ro"]="Query", + }, + ["QueryAgain"]={ + ["cs"]="QueryAgain", + ["de"]="QueryAgain", + ["en"]="QueryAgain", + ["fr"]="InterrogerSuivant", + ["it"]="RinnovaRichiesta", + ["nl"]="HerhaalRaadplegen", + ["pe"]="پرسش‌دوباره", + ["ro"]="QueryAgain", + }, + ["ResetForm"]={ + ["cs"]="ResetFormulare", + ["de"]="ZuruecksetzenFormular", + ["en"]="ResetForm", + ["fr"]="RazFormulaire", + ["it"]="ReimpostaForm", + ["nl"]="ResetFormulier", + ["pe"]="دوباره‌نشانی‌فرم", + ["ro"]="ResetareFormular", + }, + ["ResumeMovie"]={ + ["cs"]="PokracovatFilm", + ["de"]="FortsetzenFilm", + ["en"]="ResumeMovie", + ["fr"]="RepriseFilm", + ["it"]="RiprendiFilm", + ["nl"]="HervatFilm", + ["pe"]="ادامه‌فیلم", + ["ro"]="RepornesteFilm", + }, + ["ResumeRendering"]={ + ["cs"]="ResumeRendering", + ["de"]="ResumeRendering", + ["en"]="ResumeRendering", + ["fr"]="RepriseRendu", + ["it"]="ResumeRendering", + ["nl"]="HervatRendering", + ["pe"]="ادامه‌تعبیر", + ["ro"]="ResumeRendering", + }, + ["ResumeSound"]={ + ["cs"]="PokracovatZvuk", + ["de"]="ResumeSound", + ["en"]="ResumeSound", + ["fr"]="RepriseSon", + ["it"]="RiprendiSuono", + ["nl"]="HervatGeluid", + ["pe"]="ادامه‌صدا", + ["ro"]="RepornesteSunet", + }, + ["Romannumerals"]={ + ["cs"]="Rimskecislice", + ["de"]="Roemischezahlen", + ["en"]="Romannumerals", + ["fr"]="Chiffresromains", + ["it"]="Numeriromani", + ["nl"]="Romeins", + ["pe"]="اعداد‌بزرگ‌لاتین", + ["ro"]="Numereromane", + }, + ["SaveDocument"]={ + ["cs"]="UlozitDokument", + ["de"]="SpeichereDokument", + ["en"]="SaveDocument", + ["fr"]="EnregistrerDocument", + ["it"]="SalvaDocumento", + ["nl"]="BewaarDocument", + ["pe"]="ذخیره‌نوشتار", + ["ro"]="SalvareDocument", + }, + ["SaveForm"]={ + ["cs"]="UlozitFormular", + ["de"]="SpeicheFormular", + ["en"]="SaveForm", + ["fr"]="EnregistrerFormulaire", + ["it"]="SalvaForm", + ["nl"]="BewaarFormulier", + ["pe"]="ذخیره‌فرم", + ["ro"]="SalveazaFormular", + }, + ["SaveNamedDocument"]={ + ["cs"]="SaveNamedDocument", + ["de"]="SaveNamedDocument", + ["en"]="SaveNamedDocument", + ["fr"]="EnregistrerDocumentNomme", + ["it"]="SaveNamedDocument", + ["nl"]="BewaarDocumentOpNaam", + ["pe"]="ذخیره‌نوشتار‌بانام", + ["ro"]="SaveNamedDocument", + }, + ["SearchAgain"]={ + ["cs"]="HledatZnovu", + ["de"]="WeiterSuchen", + ["en"]="SearchAgain", + ["fr"]="ChercherSuivant", + ["it"]="CercaAncora", + ["nl"]="HerhaalZoeken", + ["pe"]="جستجوی‌دوباره", + ["ro"]="CautaDinNou", + }, + ["SearchDocument"]={ + ["cs"]="ProhledatDokument", + ["de"]="DokumentDurchsuchen", + ["en"]="SearchDocument", + ["fr"]="ChercherDocument", + ["it"]="CercaDocumento", + ["nl"]="DoorzoekDocument", + ["pe"]="جستجوی‌نوشتار", + ["ro"]="CautaDocument", + }, + ["ShowBookmarks"]={ + ["cs"]="UkazZalozky", + ["de"]="ShowBookmarks", + ["en"]="ShowBookmarks", + ["fr"]="MontrerMarquepages", + ["it"]="MostraSegnalibro", + ["nl"]="ShowBookmarks", + ["pe"]="نمایش‌چوبخط", + ["ro"]="ShowBookmarks", + }, + ["ShowField"]={ + ["cs"]="UkazPole", + ["de"]="ZeigeFeld", + ["en"]="ShowField", + ["fr"]="MontrerChamp", + ["it"]="MostraCampo", + ["nl"]="ToonVeld", + ["pe"]="نمایش‌میدان", + ["ro"]="AfiseazaCamp", + }, + ["ShowThumbs"]={ + ["cs"]="UkazNahledy", + ["de"]="ShowThumbs", + ["en"]="ShowThumbs", + ["fr"]="MontrerVignettes", + ["it"]="MostraThumbs", + ["nl"]="ShowThumbs", + ["pe"]="نمایش‌شصت", + ["ro"]="ShowThumbs", + }, + ["StartMovie"]={ + ["cs"]="SpustitFilm", + ["de"]="StartFilm", + ["en"]="StartMovie", + ["fr"]="débutFilm", + ["it"]="IniziaFilm", + ["nl"]="StartFilm", + ["pe"]="شروع‌فیلم", + ["ro"]="StartFilm", + }, + ["StartRendering"]={ + ["cs"]="StartRendering", + ["de"]="StartRendering", + ["en"]="StartRendering", + ["fr"]="débutRendu", + ["it"]="StartRendering", + ["nl"]="StartRendering", + ["pe"]="شروع‌تعبیر", + ["ro"]="StartRendering", + }, + ["StartSound"]={ + ["cs"]="StartZvuk", + ["de"]="StartSound", + ["en"]="StartSound", + ["fr"]="débutSon", + ["it"]="IniziaSuono", + ["nl"]="StartGeluid", + ["pe"]="شروع‌صدا", + ["ro"]="StartSunet", + }, + ["StopMovie"]={ + ["cs"]="ZastavitFilm", + ["de"]="StopFilm", + ["en"]="StopMovie", + ["fr"]="FinFilm", + ["it"]="FermaFilm", + ["nl"]="StopFilm", + ["pe"]="پایان‌فیلم", + ["ro"]="StopFilm", + }, + ["StopRendering"]={ + ["cs"]="StopRendering", + ["de"]="StopRendering", + ["en"]="StopRendering", + ["fr"]="FinRendu", + ["it"]="StopRendering", + ["nl"]="StopRendering", + ["pe"]="پایان‌تعبیر", + ["ro"]="StopRendering", + }, + ["StopSound"]={ + ["cs"]="StopZvuk", + ["de"]="StopSound", + ["en"]="StopSound", + ["fr"]="FinSon", + ["it"]="FermaSuono", + ["nl"]="StopGeluid", + ["pe"]="پایان‌صدا", + ["ro"]="StopSunet", + }, + ["SubmitForm"]={ + ["cs"]="PoslatFormular", + ["de"]="VersendeFormular", + ["en"]="SubmitForm", + ["fr"]="SoumettreFormulaire", + ["it"]="MandaForm", + ["nl"]="VerzendFormulier", + ["pe"]="تسلیم‌فرم", + ["ro"]="TrimiteFormular", + }, + ["ToggleLayer"]={ + ["cs"]="ToggleLayer", + ["de"]="ToggleLayer", + ["en"]="ToggleLayer", + ["fr"]="BasculerCalque", + ["it"]="ToggleLayer", + ["nl"]="WisselLaag", + ["pe"]="تغییرلایه", + ["ro"]="ToggleLayer", + }, + ["ToggleViewer"]={ + ["cs"]="ZmenitProhlizec", + ["de"]="WechseleViewer", + ["en"]="ToggleViewer", + ["fr"]="BasculerVisualisateur", + ["it"]="ScambiaVisualizzatore", + ["nl"]="WisselViewer", + ["pe"]="تغییرنمایشگر", + ["ro"]="SchimbaVizualizator", + }, + ["URL"]={ + ["cs"]="URL", + ["de"]="URL", + ["en"]="URL", + ["fr"]="URL", + ["it"]="URL", + ["nl"]="URL", + ["pe"]="URL", + ["ro"]="URL", + }, + ["VideLayer"]={ + ["cs"]="VideLayer", + ["de"]="VideLayer", + ["en"]="VideLayer", + ["fr"]="VideCalque", + ["it"]="VideLayer", + ["nl"]="ToonLaag", + ["pe"]="VideLayer", + ["ro"]="VideLayer", + }, + ["ViewerHelp"]={ + ["cs"]="NapovedaProhlizece", + ["de"]="ViewerHilfe", + ["en"]="ViewerHelp", + ["fr"]="AideVisualisateur", + ["it"]="AiutoVisualizzatore", + ["nl"]="ViewerHelp", + ["pe"]="کمک‌نمایشگر", + ["ro"]="AjutorVizualizator", + }, + ["WEEKDAY"]={ + ["cs"]="VSEDNIDEN", + ["de"]="WOCHENTAG", + ["en"]="WEEKDAY", + ["fr"]="JOURSEMAINE", + ["it"]="GIORNOSETTIMANA", + ["nl"]="WEEKDAG", + ["pe"]="روزهفته", + ["ro"]="ZISAPTAMANA", }, - ["continued"]={ - ["en"]="continued", - ["nl"]="vervolgd", + ["WORD"]={ + ["cs"]="SLOVO", + ["de"]="WORT", + ["en"]="WORD", + ["fr"]="MOT", + ["it"]="PAROLA", + ["nl"]="WOORD", + ["pe"]="کلمه", + ["ro"]="CUVANT", }, - ["controls"]={ - ["cs"]="controls", - ["de"]="controls", - ["en"]="controls", - ["fr"]="controles", - ["it"]="controlli", - ["nl"]="sturing", - ["pe"]="کنترلها", - ["ro"]="controale", + ["WORDS"]={ + ["cs"]="SLOVA", + ["de"]="WOERTER", + ["en"]="WORDS", + ["fr"]="MOTS", + ["it"]="PAROLE", + ["nl"]="WOORDEN", + ["pe"]="WORDS", + ["ro"]="CUVINTE", }, - ["conversion"]={ - ["cs"]="konverze", - ["de"]="konversion", - ["en"]="conversion", - ["fr"]="conversion", - ["it"]="coversione", - ["nl"]="conversie", - ["pe"]="تبدیل", - ["ro"]="conversie", + ["Word"]={ + ["cs"]="Slovo", + ["de"]="Wort", + ["en"]="Word", + ["fr"]="Mot", + ["it"]="Parola", + ["nl"]="Woord", + ["pe"]="Word", + ["ro"]="Cuvant", }, - ["current"]={ - ["cs"]="aktualni", - ["de"]="aktuell", - ["en"]="current", - ["fr"]="courant", - ["it"]="corrente", - ["nl"]="huidige", - ["pe"]="جاری", - ["ro"]="curent", + ["Words"]={ + ["cs"]="Slova", + ["de"]="Woerter", + ["en"]="Words", + ["fr"]="Mots", + ["it"]="Parole", + ["nl"]="Woorden", + ["pe"]="Words", + ["ro"]="Cuvinte", }, - ["cutspace"]={ - ["cs"]="cutspace", - ["de"]="cutspace", - ["en"]="cutspace", - ["fr"]="cutspace", - ["it"]="cutspace", - ["nl"]="snijwit", - ["pe"]="فضای‌برش", - ["ro"]="cutspace", + ["abbreviation"]={ + ["cs"]="zkratka", + ["de"]="abkuerzung", + ["en"]="abbreviation", + ["fr"]="abreviation", + ["it"]="abbreviazione", + ["nl"]="afkorting", + ["pe"]="اختصار", + ["ro"]="abreviere", }, - ["dataset"]={ - ["en"]="dataset", + ["abbreviations"]={ + ["cs"]="zkratky", + ["de"]="abkuerzungen", + ["en"]="abbreviations", + ["fr"]="abreviations", + ["it"]="abbreviazioni", + ["nl"]="afkortingen", + ["pe"]="اختصارات", + ["ro"]="abrevieri", }, - ["date"]={ - ["cs"]="datum", - ["de"]="datum", - ["en"]="date", - ["fr"]="date", - ["it"]="data", - ["nl"]="datum", - ["pe"]="تاریخ", - ["ro"]="data", + ["absolute"]={ + ["cs"]="absolutni", + ["de"]="absolut", + ["en"]="absolute", + ["fr"]="absolu", + ["it"]="assoluto", + ["nl"]="absoluut", + ["pe"]="قطعی", + ["ro"]="absolut", }, - ["day"]={ - ["cs"]="den", - ["de"]="tag", - ["en"]="day", - ["fr"]="jour", - ["it"]="giorno", - ["nl"]="dag", - ["pe"]="روز", - ["ro"]="zi", + ["action"]={ + ["cs"]="akce", + ["de"]="aktion", + ["en"]="action", + ["fr"]="action", + ["it"]="azione", + ["nl"]="actie", + ["pe"]="کنش", + ["ro"]="actiune", }, - ["december"]={ - ["cs"]="prosinec", - ["de"]="dezember", - ["en"]="december", - ["fr"]="decembre", - ["it"]="dicembre", - ["nl"]="december", - ["pe"]="دسامبر", - ["ro"]="decembrie", + ["after"]={ + ["cs"]="po", + ["de"]="nach", + ["en"]="after", + ["fr"]="après", + ["it"]="dopo", + ["nl"]="na", + ["pe"]="بعداز", + ["ro"]="dupa", }, - ["default"]={ - ["cs"]="implicitni", - ["de"]="default", - ["en"]="default", - ["fr"]="defaut", - ["it"]="implicito", - ["nl"]="default", - ["pe"]="پیش‌فرض", - ["ro"]="implicit", + ["all"]={ + ["cs"]="vse", + ["de"]="alles", + ["en"]="all", + ["fr"]="tout", + ["it"]="tutti", + ["nl"]="alles", + ["pe"]="همه", + ["ro"]="tot", }, - ["depth"]={ - ["cs"]="podlehloubky", - ["de"]="tiefe", - ["en"]="depth", - ["fr"]="profondeur", - ["it"]="profondita", - ["nl"]="diepte", - ["pe"]="عمق", - ["ro"]="adancime", + ["alphabetic"]={ + ["en"]="alphabetic", + ["fr"]="Alphabetique", }, - ["description"]={ - ["cs"]="popis", - ["de"]="beschreibung", - ["en"]="description", - ["fr"]="description", - ["it"]="descrizione", - ["nl"]="doordefinitie", - ["pe"]="شرح", - ["ro"]="descriere", + ["always"]={ + ["cs"]="vzdy", + ["de"]="immer", + ["en"]="always", + ["fr"]="toujours", + ["it"]="sempre", + ["nl"]="altijd", + ["pe"]="همواره", + ["ro"]="totdeauna", }, - ["disable"]={ - ["cs"]="zablokovat", - ["de"]="sperren", - ["en"]="disable", - ["fr"]="desactiver", - ["it"]="disattiva", - ["nl"]="blokkeer", - ["pe"]="ناتوان", - ["ro"]="dezactivat", + ["anchor"]={ + ["en"]="anchor", + ["fr"]="ancre", + ["nl"]="anker", }, - ["display"]={ - ["cs"]="obrazovka", - ["de"]="bildschirm", - ["en"]="display", - ["fr"]="affichage", - ["it"]="schermo", - ["nl"]="scherm", - ["pe"]="نمایش", - ["ro"]="display", + ["and"]={ + ["de"]="und", + ["en"]="and", + ["fr"]="et", + ["nl"]="en", + }, + ["answerarea"]={ + ["cs"]="answerarea", + ["de"]="answerarea", + ["en"]="answerarea", + ["fr"]="zonereponse", + ["it"]="answerarea", + ["nl"]="antwoordgebied", + ["pe"]="answerarea", + ["ro"]="answerarea", + }, + ["appendices"]={ + ["cs"]="dodatky", + ["de"]="anhaenge", + ["en"]="appendices", + ["fr"]="annexes", + ["it"]="appendici", + ["nl"]="bijlagen", + ["pe"]="پیوستها", + ["ro"]="apendixuri", + }, + ["appendix"]={ + ["cs"]="dodatek", + ["de"]="anhang", + ["en"]="appendix", + ["fr"]="annexe", + ["it"]="appendice", + ["nl"]="bijlage", + ["pe"]="پیوست", + ["ro"]="apendix", + }, + ["april"]={ + ["cs"]="duben", + ["de"]="april", + ["en"]="april", + ["fr"]="avril", + ["it"]="aprile", + ["nl"]="april", + ["pe"]="آوریل", + ["ro"]="aprilie", }, - ["dot"]={ - ["cs"]="tecka", - ["de"]="punkt", - ["en"]="dot", - ["fr"]="point", - ["it"]="punto", - ["nl"]="punt", - ["pe"]="نقطه", - ["ro"]="punct", + ["aside"]={ + ["en"]="aside", + ["fr"]="apart", }, - ["doublesided"]={ - ["cs"]="dvoustranny", - ["de"]="doppelseitig", - ["en"]="doublesided", - ["fr"]="rectoverso", - ["it"]="doppiafaccia", - ["nl"]="dubbelzijdig", - ["pe"]="دورو", - ["ro"]="douafete", + ["atleftmargin"]={ + ["cs"]="atleftmargin", + ["de"]="atleftmargin", + ["en"]="atleftmargin", + ["fr"]="enmargegauche", + ["it"]="atleftmargin", + ["nl"]="oplinkermarge", + ["pe"]="درحاشیه‌چپ", + ["ro"]="atleftmargin", }, - ["down"]={ - ["en"]="down", - ["nl"]="omlaag", + ["atmargin"]={ + ["cs"]="naokraji", + ["de"]="amrand", + ["en"]="atmargin", + ["fr"]="enmarge", + ["it"]="almargine", + ["nl"]="opmarge", + ["pe"]="درحاشیه", + ["ro"]="lamargine", }, - ["each"]={ - ["cs"]="kazdy", - ["de"]="jede", - ["en"]="each", - ["fr"]="chaque", - ["it"]="ogni", - ["nl"]="elk", - ["pe"]="هر", - ["ro"]="fiecare", + ["atpage"]={ + ["cs"]="nastrance", + ["de"]="aufseite", + ["en"]="atpage", + ["fr"]="enpage", + ["it"]="apagina", + ["nl"]="oppagina", + ["pe"]="درصفحه", + ["ro"]="lapagina", }, - ["edge"]={ - ["cs"]="hrana", - ["de"]="kante", - ["en"]="edge", - ["fr"]="bord", - ["it"]="bordo", - ["nl"]="rand", - ["pe"]="لبه", - ["ro"]="bordura", + ["atrightmargin"]={ + ["cs"]="atrightmargin", + ["de"]="atrightmargin", + ["en"]="atrightmargin", + ["fr"]="enmargedroite", + ["it"]="atrightmargin", + ["nl"]="oprechtermarge", + ["pe"]="درحاشیه‌راست", + ["ro"]="atrightmargin", }, - ["effective"]={ - ["en"]="effective", - ["nl"]="effectief", + ["attachment"]={ + ["en"]="attachment", + ["fr"]="piecejointe", + ["nl"]="aanhangsel", }, - ["embed"]={ - ["en"]="embed", - ["nl"]="sluitin", + ["august"]={ + ["cs"]="srpen", + ["de"]="august", + ["en"]="august", + ["fr"]="aout", + ["it"]="agosto", + ["nl"]="augustus", + ["pe"]="آگوست", + ["ro"]="august", }, - ["empty"]={ - ["cs"]="prazdne", - ["de"]="leer", - ["en"]="empty", - ["fr"]="vide", - ["it"]="vuoto", - ["nl"]="leeg", - ["pe"]="تهی", - ["ro"]="gol", + ["author"]={ + ["cs"]="autor", + ["de"]="autor", + ["en"]="author", + ["fr"]="auteur", + ["it"]="autore", + ["nl"]="auteur", + ["ro"]="autor", }, - ["enable"]={ - ["en"]="enable", + ["auto"]={ + ["cs"]="auto", + ["de"]="auto", + ["en"]="auto", + ["fr"]="auto", + ["it"]="auto", + ["nl"]="auto", + ["pe"]="خودکار", + ["ro"]="auto", }, - ["end"]={ - ["en"]="end", - ["nl"]="eind", + ["autointro"]={ + ["cs"]="autouvod", + ["de"]="autointro", + ["en"]="autointro", + ["fr"]="autointro", + ["it"]="autointro", + ["nl"]="autointro", + ["pe"]="پیشگفتارخودکار", + ["ro"]="autointro", }, - ["endnote"]={ - ["cs"]="endnote", - ["de"]="endnote", - ["en"]="endnote", - ["fr"]="notefin", - ["it"]="endnote", - ["nl"]="eindnoot", - ["pe"]="ته‌نوشت", - ["ro"]="endnote", + ["autopunctuation"]={ + ["en"]="autopunctuation", + ["fr"]="autoponctuation", }, - ["textnote"]={ - ["en"]="textnote", - ["nl"]="tekstnoot", + ["back"]={ + ["cs"]="zpet", + ["de"]="zurueck", + ["en"]="back", + ["fr"]="retour", + ["it"]="dietro", + ["nl"]="terug", + ["pe"]="پشت", + ["ro"]="inapot", }, - ["enumeration"]={ - ["cs"]="vycet", - ["de"]="nummerierung", - ["en"]="enumeration", - ["fr"]="enumeration", - ["it"]="enumerazione", - ["nl"]="doornummering", - ["pe"]="شماره‌بندی", - ["ro"]="enumerare", + ["background"]={ + ["cs"]="pozadi", + ["de"]="hintergrund", + ["en"]="background", + ["fr"]="arriereplan", + ["it"]="sfondo", + ["nl"]="achtergrond", + ["pe"]="پس‌زمینه", + ["ro"]="fundal", }, - ["environment"]={ - ["cs"]="prostredi", - ["de"]="umgebung", - ["en"]="environment", - ["fr"]="environement", - ["it"]="ambiente", - ["nl"]="omgeving", - ["pe"]="محیط", - ["ro"]="mediu", + ["backmatter"]={ + ["cs"]="epilogy", + ["de"]="epiloge", + ["en"]="backmatter", + ["fr"]="pagesdefin", + ["it"]="postambolo", + ["nl"]="uitleidingen", + ["pe"]="پس‌مطلب", + ["ro"]="epilogul", }, - ["even"]={ - ["cs"]="sude", - ["de"]="gerade", - ["en"]="even", - ["fr"]="paire", - ["it"]="pari", - ["nl"]="even", - ["pe"]="زوج", - ["ro"]="par", + ["backpart"]={ + ["cs"]="epilog", + ["de"]="epilog", + ["en"]="backpart", + ["fr"]="postface", + ["it"]="postfazione", + ["nl"]="uitleiding", + ["pe"]="پس‌قسمت", + ["ro"]="epilog", }, - ["export"]={ - ["en"]="export", + ["backspace"]={ + ["cs"]="zpetnamezera", + ["de"]="rumpfspatium", + ["en"]="backspace", + ["fr"]="retourarrière", + ["it"]="backspace", + ["nl"]="rugwit", + ["pe"]="فضای‌پشت", + ["ro"]="spatiuspate", }, - ["external"]={ - ["cs"]="externi", - ["de"]="extern", - ["en"]="external", - ["fr"]="external", - ["it"]="esterno", - ["nl"]="extern", - ["pe"]="خارجی", - ["ro"]="extern", + ["backward"]={ + ["cs"]="zpet", + ["de"]="rueckwaerts", + ["en"]="backward", + ["fr"]="enarriere", + ["it"]="indietro", + ["nl"]="achteruit", + ["pe"]="عقب‌گرد", + ["ro"]="inapoi", }, - ["extremestretch"]={ - ["en"]="extremestretch", + ["bbl"]={ + ["en"]="bbl", + ["fr"]="bbl", }, - ["fact"]={ - ["cs"]="fakt", - ["de"]="gegeben", - ["en"]="fact", - ["fr"]="fait", - ["it"]="fatto", - ["nl"]="gegeven", - ["pe"]="fact", - ["ro"]="fapt", + ["before"]={ + ["cs"]="pred", + ["de"]="vor", + ["en"]="before", + ["fr"]="avant", + ["it"]="prima", + ["nl"]="voor", + ["pe"]="قبل‌از", + ["ro"]="inainte", }, - ["february"]={ - ["cs"]="unor", - ["de"]="februar", - ["en"]="february", - ["fr"]="fevrier", - ["it"]="febbraio", - ["nl"]="februari", - ["pe"]="فوریه", - ["ro"]="februarie", + ["begin"]={ + ["en"]="begin", + ["fr"]="commencer", + ["nl"]="begin", }, - ["field"]={ - ["en"]="field", - ["nl"]="veld", + ["bib"]={ + ["en"]="bib", + ["fr"]="bib", }, - ["figure"]={ - ["cs"]="obrazek", - ["de"]="abbildung", - ["en"]="figure", - ["fr"]="figure", - ["it"]="figura", - ["nl"]="figuur", - ["pe"]="شکل", - ["ro"]="figura", + ["big"]={ + ["cs"]="velke", + ["de"]="gross", + ["en"]="big", + ["fr"]="important", + ["it"]="grande", + ["nl"]="groot", + ["pe"]="بزرگ", + ["ro"]="mare", }, - ["figures"]={ - ["cs"]="obrazky", - ["de"]="abbildungen", - ["en"]="figures", - ["fr"]="figures", - ["it"]="figure", - ["nl"]="figuren", - ["pe"]="شکلها", - ["ro"]="figure", + ["bigbodyfont"]={ + ["cs"]="bigbodyfont", + ["de"]="bigbodyfont", + ["en"]="bigbodyfont", + ["fr"]="policedecorpsimportante", + ["it"]="grossofontdeltesto", + ["nl"]="grootkorps", + ["pe"]="قلم‌بدنه‌بزرگ", + ["ro"]="bigbodyfont", }, - ["file"]={ - ["cs"]="soubor", - ["de"]="datei", - ["en"]="file", - ["fr"]="fichier", - ["it"]="file", - ["nl"]="file", - ["pe"]="پرونده", - ["ro"]="fisier", + ["bigger"]={ + ["en"]="bigger", + ["fr"]="plusimportant", + ["nl"]="groter", }, - ["final"]={ - ["cs"]="finalni", - ["de"]="endfassung", - ["en"]="final", - ["fr"]="final", - ["it"]="finale", - ["nl"]="definitief", - ["pe"]="نهایی", - ["ro"]="final", + ["bigpreference"]={ + ["cs"]="vysokapriorita", + ["de"]="grosszuegig", + ["en"]="bigpreference", + ["fr"]="preferenceimportante", + ["it"]="grandepreferenza", + ["nl"]="grotevoorkeur", + ["pe"]="اولویت‌بزرگ", + ["ro"]="preferintamare", }, - ["first"]={ - ["cs"]="prvni", - ["de"]="erste", - ["en"]="first", - ["fr"]="premier", - ["it"]="primo", - ["nl"]="eerste", - ["pe"]="اولی", - ["ro"]="primul", + ["blank"]={ + ["cs"]="prazdny", + ["de"]="blanko", + ["en"]="blank", + ["fr"]="vierge", + ["it"]="rigovuoto", + ["nl"]="blanko", + ["pe"]="خالی", + ["ro"]="blank", }, - ["firstcolumn"]={ - ["cs"]="firstcolumn", - ["de"]="firstcolumn", - ["en"]="firstcolumn", - ["fr"]="premierecolonne", - ["it"]="firstcolumn", - ["nl"]="eerstekolom", - ["pe"]="ستون‌اول", - ["ro"]="firstcolumn", + ["block"]={ + ["en"]="block", + ["fr"]="bloc", }, - ["firstpage"]={ - ["cs"]="prvnistranka", - ["de"]="ersteseite", - ["en"]="firstpage", - ["fr"]="premierepage", - ["it"]="primapagina", - ["nl"]="eerstepagina", - ["pe"]="صفحه‌اول", - ["ro"]="primapagina", + ["blockquote"]={ + ["cs"]="blockquote", + ["de"]="blockquote", + ["en"]="blockquote", + ["fr"]="citerbloc", + ["it"]="blockquote", + ["nl"]="blokcitaat", + ["pe"]="نقل‌بلوک", + ["ro"]="blockquote", }, - ["firstsubpage"]={ - ["cs"]="prvnipodstranka", - ["de"]="ersteunterseite", - ["en"]="firstsubpage", - ["fr"]="premieresouspage", - ["it"]="primasottopagina", - ["nl"]="eerstesubpagina", - ["pe"]="زیرصفحه‌اول", - ["ro"]="primasubpagina", + ["bodymatter"]={ + ["cs"]="hlavnicasti", + ["de"]="haupttexte", + ["en"]="bodymatter", + ["fr"]="pagescorpsdetexte", + ["it"]="testiprincipali", + ["nl"]="hoofdteksten", + ["pe"]="مطلب‌بدنه", + ["ro"]="principalul", }, - ["fit"]={ - ["cs"]="prizpusobive", - ["de"]="passend", - ["en"]="fit", - ["fr"]="adapte", - ["it"]="adatta", - ["nl"]="passend", - ["pe"]="پرکردن", - ["ro"]="ajustat", + ["bodypart"]={ + ["cs"]="hlavnicast", + ["de"]="haupttext", + ["en"]="bodypart", + ["fr"]="corpsdetexte", + ["it"]="testoprincipale", + ["nl"]="hoofdtekst", + ["pe"]="قسمت‌بدنه", + ["ro"]="principal", }, - ["five"]={ - ["cs"]="pet", - ["de"]="fuenf", - ["en"]="five", - ["fr"]="cinq", - ["it"]="cinque", - ["nl"]="vijf", - ["pe"]="پنج", - ["ro"]="cinci", + ["bold"]={ + ["cs"]="tucne", + ["de"]="fett", + ["en"]="bold", + ["fr"]="gras", + ["it"]="grassetto", + ["nl"]="vet", + ["pe"]="مشکی", + ["ro"]="aldin", }, - ["six"]={ - ["cs"]="six", - ["de"]="sechs", - ["en"]="six", - ["fr"]="six", - ["it"]="six", - ["nl"]="zes", - ["pe"]="six", - ["ro"]="six", + ["bolditalic"]={ + ["cs"]="tucnekurzivni", + ["de"]="fettitalic", + ["en"]="bolditalic", + ["fr"]="grasitalique", + ["it"]="grassettocorsivo", + ["nl"]="vetitalic", + ["pe"]="ایتالیک‌مشکی", + ["ro"]="aldinitalic", }, - ["seven"]={ - ["cs"]="seven", - ["de"]="sieben", - ["en"]="seven", - ["fr"]="seven", - ["it"]="seven", - ["nl"]="zeven", - ["pe"]="seven", - ["ro"]="seven", + ["boldslanted"]={ + ["cs"]="tucnesklonene", + ["de"]="fettgeneigt", + ["en"]="boldslanted", + ["fr"]="grasincline", + ["it"]="grassettoinclinato", + ["nl"]="vetschuin", + ["pe"]="خوابیده‌مشکی", + ["ro"]="aldininclinat", }, - ["eight"]={ - ["cs"]="eight", - ["de"]="acht", - ["en"]="eight", - ["fr"]="eight", - ["it"]="eight", - ["nl"]="acht", - ["pe"]="eight", - ["ro"]="eight", + ["bookmark"]={ + ["cs"]="zalozka", + ["de"]="bookmark", + ["en"]="bookmark", + ["fr"]="marquepage", + ["it"]="segnalibro", + ["nl"]="bookmark", + ["pe"]="چوبخط", + ["ro"]="semncarte", }, - ["nine"]={ - ["cs"]="nine", - ["de"]="neun", - ["en"]="nine", - ["fr"]="nine", - ["it"]="nine", - ["nl"]="negen", - ["pe"]="nine", - ["ro"]="nine", + ["both"]={ + ["cs"]="obe", + ["de"]="beide", + ["en"]="both", + ["fr"]="chacun", + ["it"]="entrambi", + ["nl"]="beide", + ["pe"]="هردو", + ["ro"]="ambele", }, - ["fix"]={ - ["cs"]="fixuj", - ["de"]="stellewiederher", - ["en"]="fix", - ["fr"]="fixe", - ["it"]="fisso", - ["nl"]="herstel", - ["pe"]="ثابت‌کن", - ["ro"]="fix", + ["bothtext"]={ + ["en"]="bothtext", + ["fr"]="textechacun", }, - ["fixed"]={ - ["cs"]="fixne", - ["de"]="fest", - ["en"]="fixed", - ["fr"]="fixe", - ["it"]="fisso", - ["nl"]="vast", - ["pe"]="ثابت", - ["ro"]="fixat", + ["bottom"]={ + ["cs"]="spodek", + ["de"]="unten", + ["en"]="bottom", + ["fr"]="bas", + ["it"]="fondo", + ["nl"]="onder", + ["pe"]="پایین", + ["ro"]="subsol", }, - ["flexible"]={ - ["cs"]="prizpusobive", - ["de"]="flexibel", - ["en"]="flexible", - ["fr"]="flexible", - ["it"]="flessibile", - ["nl"]="flexibel", - ["pe"]="انعطافپذیر", - ["ro"]="flexibil", + ["box"]={ + ["en"]="box", + ["fr"]="boite", }, - ["float"]={ - ["cs"]="plvouciobjekt", - ["de"]="gleitobjekt", - ["en"]="float", - ["fr"]="flottant", - ["it"]="oggettomobile", - ["nl"]="blok", - ["pe"]="شناور", - ["ro"]="obiectmobil", + ["brief"]={ + ["cs"]="brief", + ["de"]="brief", + ["en"]="brief", + ["fr"]="brief", + ["it"]="brief", + ["nl"]="brief", + ["pe"]="مختصر", + ["ro"]="brief", }, - ["flushinner"]={ - ["cs"]="flushinner", - ["de"]="flushinner", - ["en"]="flushinner", - ["fr"]="flushinner", - ["it"]="flushinner", - ["nl"]="lijnbinnen", - ["pe"]="پمپ‌داخلی", - ["ro"]="flushinner", + ["broad"]={ + ["cs"]="siroky", + ["de"]="breit", + ["en"]="broad", + ["fr"]="large", + ["it"]="ampio", + ["nl"]="ruim", + ["pe"]="گسترده", + ["ro"]="broad", }, - ["flushleft"]={ - ["cs"]="flushleft", - ["de"]="flushleft", - ["en"]="flushleft", - ["fr"]="flushleft", - ["it"]="flushleft", - ["nl"]="lijnlinks", - ["pe"]="پمپ‌چپ", - ["ro"]="flushleft", + ["buffer"]={ + ["cs"]="buffer", + ["de"]="puffer", + ["en"]="buffer", + ["fr"]="tampon", + ["it"]="buffer", + ["nl"]="buffer", + ["pe"]="بافر", + ["ro"]="buffer", }, - ["flushouter"]={ - ["cs"]="flushouter", - ["de"]="flushouter", - ["en"]="flushouter", - ["fr"]="flushouter", - ["it"]="flushouter", - ["nl"]="lijnbuiten", - ["pe"]="پمپ‌خارجی", - ["ro"]="flushouter", + ["by"]={ + ["cs"]="skrz", + ["de"]="pro", + ["en"]="by", + ["fr"]="par", + ["it"]="da", + ["nl"]="per", + ["pe"]="بوسیله", + ["ro"]="de", }, - ["flushright"]={ - ["cs"]="flushright", - ["de"]="flushright", - ["en"]="flushright", - ["fr"]="flushright", - ["it"]="flushright", - ["nl"]="lijnrechts", - ["pe"]="پمپ‌راست", - ["ro"]="flushright", + ["calligraphic"]={ + ["cs"]="kaligraficke", + ["de"]="kalligraphie", + ["en"]="calligraphic", + ["fr"]="calligraphique", + ["it"]="calligrafico", + ["nl"]="calligrafie", + ["pe"]="خوشنویسی", + ["ro"]="caligrafic", }, - ["followingpage"]={ - ["en"]="followingpage", - ["nl"]="opvolgendepagina", + ["camel"]={ + ["en"]="camel", + ["fr"]="camel", }, - ["footer"]={ - ["cs"]="upati", - ["de"]="fusszeile", - ["en"]="footer", - ["fr"]="pdp", - ["it"]="piedipagina", - ["nl"]="voet", - ["pe"]="ته‌برگ", - ["ro"]="subsol", + ["cap"]={ + ["cs"]="kap", + ["de"]="kap", + ["en"]="cap", + ["fr"]="cap", + ["it"]="cap", + ["nl"]="kap", + ["pe"]="cap", + ["ro"]="cap", }, - ["footnote"]={ - ["cs"]="poznamkapodcarou", - ["de"]="fussnote", - ["en"]="footnote", - ["fr"]="notepdp", - ["it"]="notapdp", - ["nl"]="voetnoot", - ["pe"]="پانوشت", - ["ro"]="notasubsol", + ["capital"]={ + ["cs"]="kapitalky", + ["de"]="versalien", + ["en"]="capital", + ["fr"]="capitales", + ["it"]="maiuscolo", + ["nl"]="kapitaal", + ["pe"]="capital", + ["ro"]="majuscula", }, - ["force"]={ - ["cs"]="sila", - ["de"]="zwinge", - ["en"]="force", - ["fr"]="force", - ["it"]="forza", - ["nl"]="forceer", - ["pe"]="اجبار", - ["ro"]="fortat", + ["center"]={ + ["cs"]="center", + ["de"]="center", + ["en"]="center", + ["fr"]="centrer", + ["it"]="center", + ["nl"]="centreer", + ["pe"]="مرکز", + ["ro"]="center", }, - ["foreground"]={ - ["cs"]="popredi", - ["de"]="vordergrund", - ["en"]="foreground", - ["fr"]="premierplan", - ["it"]="foreground", - ["nl"]="voorgrond", - ["pe"]="پیش‌زمینه", - ["ro"]="primplan", + ["centerlast"]={ + ["en"]="centerlast", + ["fr"]="centrerdernier", }, - ["formula"]={ - ["cs"]="rovnice", - ["de"]="formel", - ["en"]="formula", - ["fr"]="formule", - ["it"]="formula", - ["nl"]="formule", - ["pe"]="فرمول", - ["ro"]="formula", + ["chapter"]={ + ["cs"]="kapitola", + ["de"]="kapitel", + ["en"]="chapter", + ["fr"]="chapitre", + ["it"]="capitolo", + ["nl"]="hoofdstuk", + ["pe"]="فصل", + ["ro"]="capitol", }, - ["formulas"]={ - ["cs"]="rovnice", - ["de"]="formeln", - ["en"]="formulas", - ["fr"]="formules", - ["it"]="formule", - ["nl"]="formules", - ["pe"]="فرمولها", - ["ro"]="formule", + ["character"]={ + ["cs"]="pismeno", + ["de"]="buchstabe", + ["en"]="character", + ["fr"]="caractere", + ["it"]="lettera", + ["nl"]="letter", + ["pe"]="حرف", + ["ro"]="caracter", }, - ["forward"]={ - ["cs"]="vpred", - ["de"]="vorwaerts", - ["en"]="forward", - ["fr"]="avance", - ["it"]="avanti", - ["nl"]="vooruit", - ["pe"]="به‌جلو", - ["ro"]="avans", + ["characters"]={ + ["cs"]="pismena", + ["de"]="buchstaben", + ["en"]="characters", + ["fr"]="caracteres", + ["it"]="lettere", + ["nl"]="letters", + ["pe"]="حرفها", + ["ro"]="caractere", }, - ["four"]={ - ["cs"]="ctyri", - ["de"]="vier", - ["en"]="four", - ["fr"]="quatre", - ["it"]="quattro", - ["nl"]="vier", - ["pe"]="چهار", - ["ro"]="patru", + ["chemical"]={ + ["en"]="chemical", + ["fr"]="chimique", }, - ["frame"]={ - ["cs"]="ramecek", - ["de"]="rahmen", - ["en"]="frame", - ["fr"]="cadre", - ["it"]="cornice", - ["nl"]="kader", - ["pe"]="قالب", - ["ro"]="incadrat", + ["chemicals"]={ + ["en"]="chemicals", + ["fr"]="chimiques", }, - ["framedtext"]={ - ["cs"]="oramovanytext", - ["de"]="umrahmtertext", - ["en"]="framedtext", - ["fr"]="texteencadre", - ["it"]="testoincorniciato", - ["nl"]="kadertekst", - ["pe"]="متن‌قالبی", - ["ro"]="textinconjurat", + ["chemistry"]={ + ["en"]="chemistry", + ["fr"]="chimie", + ["nl"]="chemie", }, - ["friday"]={ - ["cs"]="patek", - ["de"]="freitag", - ["en"]="friday", - ["fr"]="vendredi", - ["it"]="venerdi", - ["nl"]="vrijdag", - ["pe"]="جمعه", - ["ro"]="vineri", + ["cite"]={ + ["en"]="cite", + ["fr"]="cite", }, - ["frontmatter"]={ - ["cs"]="prednicasti", - ["de"]="einleitungen", - ["en"]="frontmatter", - ["fr"]="preambule", - ["it"]="preambolo", - ["nl"]="inleidingen", - ["pe"]="پیش‌مطلب", - ["ro"]="prologul", + ["closed"]={ + ["en"]="closed", + ["fr"]="ferme", + ["nl"]="gesloten", }, - ["frontpart"]={ - ["cs"]="prednicast", - ["de"]="einleitung", - ["en"]="frontpart", - ["fr"]="preface", - ["it"]="prefazione", - ["nl"]="inleiding", - ["pe"]="پیش‌قسمت", - ["ro"]="prolog", + ["color"]={ + ["cs"]="barevne", + ["de"]="farbe", + ["en"]="color", + ["fr"]="couleur", + ["it"]="colore", + ["nl"]="kleur", + ["pe"]="رنگ", + ["ro"]="culoare", }, - ["fullhz"]={ - ["cs"]="fullhz", - ["de"]="fullhz", - ["en"]="fullhz", - ["fr"]="fullhz", - ["it"]="fullhz", - ["nl"]="fullenhz", - ["pe"]="fullhz", - ["ro"]="fullhz", + ["column"]={ + ["cs"]="column", + ["de"]="column", + ["en"]="column", + ["fr"]="colonne", + ["it"]="colonna", + ["nl"]="kolom", + ["pe"]="ستون", + ["ro"]="coloana", }, - ["global"]={ - ["cs"]="globalne", - ["de"]="global", - ["en"]="global", - ["fr"]="global", - ["it"]="globale", - ["nl"]="globaal", - ["pe"]="سراسری", - ["ro"]="global", + ["columns"]={ + ["cs"]="sloupce", + ["de"]="spalten", + ["en"]="columns", + ["fr"]="colonnes", + ["it"]="colonne", + ["nl"]="kolommen", + ["pe"]="ستونها", + ["ro"]="coloane", }, - ["graphic"]={ - ["cs"]="graf", - ["de"]="grafik", - ["en"]="graphic", - ["fr"]="graphique", - ["it"]="grafico", - ["nl"]="grafiek", - ["pe"]="گرافیک", - ["ro"]="graficul", + ["combination"]={ + ["en"]="combination", + ["fr"]="combinaison", + ["nl"]="combinatie", }, - ["graphics"]={ - ["cs"]="grafy", - ["de"]="grafiken", - ["en"]="graphics", - ["fr"]="graphiques", - ["it"]="grafici", - ["nl"]="grafieken", - ["pe"]="گرافیکها", - ["ro"]="graficele", + ["command"]={ + ["cs"]="prikaz", + ["de"]="befehl", + ["en"]="command", + ["fr"]="commande", + ["it"]="comando", + ["nl"]="commando", + ["pe"]="فرمان", + ["ro"]="comanda", }, - ["gray"]={ - ["cs"]="seda", - ["de"]="grau", - ["en"]="gray", - ["fr"]="gris", - ["it"]="grigio", - ["nl"]="grijs", - ["pe"]="خاکستری", - ["ro"]="gri", + ["commands"]={ + ["cs"]="prikazy", + ["de"]="befehle", + ["en"]="commands", + ["fr"]="commandes", + ["it"]="comandi", + ["nl"]="commandos", + ["pe"]="فرمانها", + ["ro"]="comenzi", }, - ["greek"]={ - ["cs"]="recky", - ["de"]="griechisch", - ["en"]="greek", - ["fr"]="grec", - ["it"]="greco", - ["nl"]="grieks", - ["pe"]="یونانی", - ["ro"]="grec", + ["comment"]={ + ["cs"]="komentar", + ["de"]="kommentar", + ["en"]="comment", + ["fr"]="commentaire", + ["it"]="commento", + ["nl"]="commentaar", + ["pe"]="توضیح", + ["ro"]="comentariu", }, - ["grid"]={ - ["cs"]="mrizka", - ["de"]="gritter", - ["en"]="grid", - ["fr"]="grille", - ["it"]="griglia", - ["nl"]="grid", - ["pe"]="توری", - ["ro"]="grila", + ["component"]={ + ["cs"]="komponenta", + ["de"]="komponente", + ["en"]="component", + ["fr"]="composant", + ["it"]="componente", + ["nl"]="onderdeel", + ["pe"]="مولفه", + ["ro"]="componenta", }, - ["halfline"]={ - ["cs"]="pulradku", - ["de"]="halbezeile", - ["en"]="halfline", - ["fr"]="demiligne", - ["it"]="mezzariga", - ["nl"]="halveregel", - ["pe"]="نیم‌خط", - ["ro"]="jumatatelinie", + ["compressseparator"]={ + ["en"]="compressseparator", + ["fr"]="separateurreduction", }, - ["handwritten"]={ - ["cs"]="rukopisne", - ["de"]="handschrift", - ["en"]="handwritten", - ["fr"]="manuscript", - ["it"]="grafiamanuale", - ["nl"]="handschrift", - ["pe"]="دست‌نوشته", - ["ro"]="scrismanual", + ["compressstopper"]={ + ["en"]="compressstopper", + ["fr"]="stoppeurreduction", }, - ["hang"]={ - ["cs"]="zaveseni", - ["de"]="haengend", - ["en"]="hang", - ["fr"]="suspend", - ["it"]="sospendi", - ["nl"]="hang", - ["pe"]="بیاویز", - ["ro"]="suspenda", + ["concept"]={ + ["cs"]="koncept", + ["de"]="konzept", + ["en"]="concept", + ["fr"]="concept", + ["it"]="concetto", + ["nl"]="concept", + ["pe"]="مفهوم", + ["ro"]="concept", }, - ["hanging"]={ - ["cs"]="visici", - ["de"]="haengend", - ["en"]="hanging", - ["fr"]="suspend", - ["it"]="sospeso", - ["nl"]="hangend", - ["pe"]="آویزان", - ["ro"]="suspendat", + ["construction"]={ + ["en"]="construction", + ["fr"]="construction", }, - ["hangingboth"]={ - ["en"]="hangingboth", - ["nl"]="beidehangend", + ["content"]={ + ["cs"]="obsah", + ["de"]="inhalt", + ["en"]="content", + ["fr"]="contenu", + ["it"]="indice", + ["nl"]="inhoud", + ["pe"]="محتوا", + ["ro"]="cuprins", }, - ["head"]={ - ["cs"]="hlavicka", - ["de"]="kopf", - ["en"]="head", - ["fr"]="tete", - ["it"]="testa", - ["nl"]="kop", - ["pe"]="سر", - ["ro"]="antet", + ["contents"]={ + ["cs"]="obsah", + ["de"]="inhalte", + ["en"]="contents", + ["fr"]="contenus", + ["it"]="indici", + ["nl"]="inhouden", + ["pe"]="محتویات", + ["ro"]="cuprinsuri", + }, + ["continue"]={ + ["cs"]="pokracovat", + ["de"]="fortsetzten", + ["en"]="continue", + ["fr"]="continuer", + ["it"]="continua", + ["nl"]="verder", + ["pe"]="ادامه", + ["ro"]="continuu", }, - ["header"]={ - ["cs"]="zahlavi", - ["de"]="kopfzeile", - ["en"]="header", - ["fr"]="entete", - ["it"]="intestazione", - ["nl"]="hoofd", - ["pe"]="سربرگ", - ["ro"]="antet", + ["continued"]={ + ["en"]="continued", + ["fr"]="continue", + ["nl"]="vervolgd", }, - ["height"]={ - ["cs"]="vyska", - ["de"]="hoehe", - ["en"]="height", - ["fr"]="hauteur", - ["it"]="altezza", - ["nl"]="hoogte", - ["pe"]="ارتفاع", - ["ro"]="inaltime", + ["controls"]={ + ["cs"]="controls", + ["de"]="controls", + ["en"]="controls", + ["fr"]="controles", + ["it"]="controlli", + ["nl"]="sturing", + ["pe"]="کنترلها", + ["ro"]="controale", }, - ["helptext"]={ - ["cs"]="textnapovedy", - ["de"]="hilfetext", - ["en"]="helptext", - ["fr"]="texteaide", - ["it"]="testoaiuto", - ["nl"]="helptekst", - ["pe"]="متن‌کمکی", - ["ro"]="textajutator", + ["conversion"]={ + ["cs"]="konverze", + ["de"]="konversion", + ["en"]="conversion", + ["fr"]="conversion", + ["it"]="coversione", + ["nl"]="conversie", + ["pe"]="تبدیل", + ["ro"]="conversie", }, - ["hencefore"]={ - ["cs"]="vyse", - ["de"]="vorher", - ["en"]="hencefore", - ["fr"]="precedent", - ["it"]="precedente", - ["nl"]="hierboven", - ["pe"]="hencefore", - ["ro"]="precedent", + ["current"]={ + ["cs"]="aktualni", + ["de"]="aktuell", + ["en"]="current", + ["fr"]="courant", + ["it"]="corrente", + ["nl"]="huidige", + ["pe"]="جاری", + ["ro"]="curent", }, - ["here"]={ - ["cs"]="zde", - ["de"]="hier", - ["en"]="here", - ["fr"]="ici", - ["it"]="qui", - ["nl"]="hier", - ["pe"]="اینجا", - ["ro"]="aici", + ["cutspace"]={ + ["cs"]="cutspace", + ["de"]="cutspace", + ["en"]="cutspace", + ["fr"]="espacecoupe", + ["it"]="cutspace", + ["nl"]="snijwit", + ["pe"]="فضای‌برش", + ["ro"]="cutspace", }, - ["hereafter"]={ - ["cs"]="nize", - ["de"]="nachher", - ["en"]="hereafter", - ["fr"]="suivant", - ["it"]="seguente", - ["nl"]="hieronder", - ["pe"]="ازاین‌به‌بعد", - ["ro"]="urmator", + ["dataset"]={ + ["en"]="dataset", + ["fr"]="jeudedonnees", }, - ["hidden"]={ - ["cs"]="skryte", - ["de"]="versteckt", - ["en"]="hidden", - ["fr"]="cache", - ["it"]="nascosto", - ["nl"]="verborgen", - ["pe"]="پنهانی", - ["ro"]="ascuns", + ["date"]={ + ["cs"]="datum", + ["de"]="datum", + ["en"]="date", + ["fr"]="date", + ["it"]="data", + ["nl"]="datum", + ["pe"]="تاریخ", + ["ro"]="data", }, - ["hiddenbar"]={ - ["en"]="hiddenbar", + ["day"]={ + ["cs"]="den", + ["de"]="tag", + ["en"]="day", + ["fr"]="jour", + ["it"]="giorno", + ["nl"]="dag", + ["pe"]="روز", + ["ro"]="zi", }, - ["hiding"]={ - ["cs"]="skryt", - ["de"]="verbergen", - ["en"]="hiding", - ["fr"]="cache", - ["it"]="nascondere", - ["nl"]="verbergen", - ["pe"]="پنهان‌کردن", - ["ro"]="ascundere", + ["december"]={ + ["cs"]="prosinec", + ["de"]="dezember", + ["en"]="december", + ["fr"]="decembre", + ["it"]="dicembre", + ["nl"]="december", + ["pe"]="دسامبر", + ["ro"]="decembrie", }, - ["high"]={ - ["cs"]="vysoko", - ["de"]="hoch", - ["en"]="high", - ["fr"]="haut", - ["it"]="alto", - ["nl"]="hoog", - ["pe"]="بلند", - ["ro"]="inalt", + ["default"]={ + ["cs"]="implicitni", + ["de"]="default", + ["en"]="default", + ["fr"]="defaut", + ["it"]="implicito", + ["nl"]="default", + ["pe"]="پیش‌فرض", + ["ro"]="implicit", }, - ["horizontal"]={ - ["cs"]="horizontalne", - ["de"]="horizontal", - ["en"]="horizontal", - ["fr"]="horizontale", - ["it"]="orizzontale", - ["nl"]="horizontaal", - ["pe"]="افقی", - ["ro"]="orizontal", + ["depth"]={ + ["cs"]="podlehloubky", + ["de"]="tiefe", + ["en"]="depth", + ["fr"]="profondeur", + ["it"]="profondita", + ["nl"]="diepte", + ["pe"]="عمق", + ["ro"]="adancime", }, - ["hyphenated"]={ - ["cs"]="hyphenated", - ["de"]="hyphenate", - ["en"]="hyphenated", - ["fr"]="hyphenated", - ["it"]="sillabato", - ["nl"]="afgebroken", - ["pe"]="شکسته", - ["ro"]="despsilabe", + ["description"]={ + ["cs"]="popis", + ["de"]="beschreibung", + ["en"]="description", + ["fr"]="description", + ["it"]="descrizione", + ["nl"]="doordefinitie", + ["pe"]="شرح", + ["ro"]="descriere", }, - ["hz"]={ - ["cs"]="hz", - ["de"]="hz", - ["en"]="hz", - ["fr"]="hz", - ["it"]="hz", - ["nl"]="hz", - ["pe"]="hz", - ["ro"]="hz", + ["disable"]={ + ["cs"]="zablokovat", + ["de"]="sperren", + ["en"]="disable", + ["fr"]="desactiver", + ["it"]="disattiva", + ["nl"]="blokkeer", + ["pe"]="ناتوان", + ["ro"]="dezactivat", }, - ["inbetween"]={ - ["cs"]="mezi", - ["de"]="zwischen", - ["en"]="inbetween", - ["fr"]="entre", - ["it"]="tra", - ["nl"]="tussen", - ["pe"]="دربین", - ["ro"]="intre", + ["display"]={ + ["cs"]="obrazovka", + ["de"]="bildschirm", + ["en"]="display", + ["fr"]="affichage", + ["it"]="schermo", + ["nl"]="scherm", + ["pe"]="نمایش", + ["ro"]="display", }, - ["index"]={ - ["cs"]="rejstrik", - ["de"]="index", - ["en"]="index", - ["fr"]="index", - ["it"]="indiceanalitico", - ["nl"]="index", - ["pe"]="نمایه", - ["ro"]="index", + ["dot"]={ + ["cs"]="tecka", + ["de"]="punkt", + ["en"]="dot", + ["fr"]="point", + ["it"]="punto", + ["nl"]="punt", + ["pe"]="نقطه", + ["ro"]="punct", + }, + ["doublesided"]={ + ["cs"]="dvoustranny", + ["de"]="doppelseitig", + ["en"]="doublesided", + ["fr"]="rectoverso", + ["it"]="doppiafaccia", + ["nl"]="dubbelzijdig", + ["pe"]="دورو", + ["ro"]="douafete", }, - ["indices"]={ - ["cs"]="rejstriky", - ["de"]="indizies", - ["en"]="indices", - ["fr"]="indices", - ["it"]="indicianalitici", - ["nl"]="indices", - ["pe"]="نمایه‌ها", - ["ro"]="indexuri", + ["down"]={ + ["en"]="down", + ["fr"]="enbas", + ["nl"]="omlaag", }, - ["inherit"]={ - ["cs"]="inherit", - ["de"]="inherit", - ["en"]="inherit", - ["fr"]="herite", - ["it"]="inherit", - ["nl"]="erf", - ["pe"]="ارث‌بردن", - ["ro"]="inherit", + ["each"]={ + ["cs"]="kazdy", + ["de"]="jede", + ["en"]="each", + ["fr"]="chaque", + ["it"]="ogni", + ["nl"]="elk", + ["pe"]="هر", + ["ro"]="fiecare", }, - ["ininner"]={ - ["cs"]="ininner", - ["de"]="ininner", - ["en"]="ininner", - ["fr"]="ininner", - ["it"]="ininner", - ["nl"]="inbinnen", - ["pe"]="درداخلی", - ["ro"]="ininner", + ["edge"]={ + ["cs"]="hrana", + ["de"]="kante", + ["en"]="edge", + ["fr"]="bord", + ["it"]="bordo", + ["nl"]="rand", + ["pe"]="لبه", + ["ro"]="bordura", }, - ["ininneredge"]={ - ["en"]="ininneredge", + ["effective"]={ + ["en"]="effective", + ["fr"]="effectif", + ["nl"]="effectief", }, - ["ininnermargin"]={ - ["en"]="ininnermargin", + ["eight"]={ + ["cs"]="eight", + ["de"]="acht", + ["en"]="eight", + ["fr"]="huit", + ["it"]="eight", + ["nl"]="acht", + ["pe"]="eight", + ["ro"]="eight", }, - ["inleft"]={ - ["cs"]="ivlevo", - ["de"]="imlinken", - ["en"]="inleft", - ["fr"]="dansgauche", - ["it"]="insinistra", - ["nl"]="inlinker", - ["pe"]="درون‌چپ", - ["ro"]="instanga", + ["embed"]={ + ["en"]="embed", + ["fr"]="integrer", + ["nl"]="sluitin", }, - ["inleftedge"]={ - ["cs"]="nalevo", - ["de"]="imlinkenrand", - ["en"]="inleftedge", - ["fr"]="dansbordgauche", - ["it"]="inlatosinistro", - ["nl"]="inlinkerrand", - ["pe"]="درلبه‌چپ", - ["ro"]="inparteastanga", + ["empty"]={ + ["cs"]="prazdne", + ["de"]="leer", + ["en"]="empty", + ["fr"]="vide", + ["it"]="vuoto", + ["nl"]="leeg", + ["pe"]="تهی", + ["ro"]="gol", }, - ["inleftmargin"]={ - ["cs"]="nalevyokraj", - ["de"]="inlinkermarginale", - ["en"]="inleftmargin", - ["fr"]="dansmargegauche", - ["it"]="inmarginesinistro", - ["nl"]="inlinkermarge", - ["pe"]="درحاشیه‌چپ", - ["ro"]="inmargineastanga", + ["enable"]={ + ["en"]="enable", + ["fr"]="activer", }, - ["inline"]={ - ["en"]="inline", + ["end"]={ + ["en"]="end", + ["fr"]="terminer", + ["nl"]="eind", }, - ["inmargin"]={ - ["cs"]="naokraji", - ["de"]="imrand", - ["en"]="inmargin", - ["fr"]="dansmarge", - ["it"]="inmargine", - ["nl"]="inmarge", - ["pe"]="درون‌حاشیه", - ["ro"]="inmargine", + ["endnote"]={ + ["cs"]="endnote", + ["de"]="endnote", + ["en"]="endnote", + ["fr"]="noteseule", + ["it"]="endnote", + ["nl"]="eindnoot", + ["pe"]="ته‌نوشت", + ["ro"]="endnote", }, - ["inner"]={ - ["cs"]="uvnitr", - ["de"]="innen", - ["en"]="inner", - ["fr"]="interieur", - ["it"]="interno", - ["nl"]="binnen", - ["pe"]="داخلی", - ["ro"]="intern", + ["enumeration"]={ + ["cs"]="vycet", + ["de"]="nummerierung", + ["en"]="enumeration", + ["fr"]="énumération", + ["it"]="enumerazione", + ["nl"]="doornummering", + ["pe"]="شماره‌بندی", + ["ro"]="enumerare", }, - ["inneredge"]={ - ["cs"]="inneredge", - ["de"]="inneredge", - ["en"]="inneredge", - ["fr"]="bordinterieur", - ["it"]="bordointerno", - ["nl"]="binnenrand", - ["pe"]="لبه‌داخلی", - ["ro"]="inneredge", + ["environment"]={ + ["cs"]="prostredi", + ["de"]="umgebung", + ["en"]="environment", + ["fr"]="environnement", + ["it"]="ambiente", + ["nl"]="omgeving", + ["pe"]="محیط", + ["ro"]="mediu", }, - ["innermargin"]={ - ["cs"]="innermargin", - ["de"]="innermargin", - ["en"]="innermargin", - ["fr"]="margeinterieure", - ["it"]="margineinterno", - ["nl"]="binnenmarge", - ["pe"]="حاشیه‌داخلی", - ["ro"]="innermargin", + ["even"]={ + ["cs"]="sude", + ["de"]="gerade", + ["en"]="even", + ["fr"]="paire", + ["it"]="pari", + ["nl"]="even", + ["pe"]="زوج", + ["ro"]="par", }, - ["inother"]={ - ["cs"]="inother", - ["de"]="inother", - ["en"]="inother", - ["fr"]="inother", - ["it"]="inother", - ["nl"]="inandere", - ["pe"]="inother", - ["ro"]="inother", + ["export"]={ + ["en"]="export", + ["fr"]="exporter", }, - ["inouter"]={ - ["cs"]="inouter", - ["de"]="inouter", - ["en"]="inouter", - ["fr"]="inouter", - ["it"]="inouter", - ["nl"]="inbuiten", - ["pe"]="درخارجی", - ["ro"]="inouter", + ["external"]={ + ["cs"]="externi", + ["de"]="extern", + ["en"]="external", + ["fr"]="externe", + ["it"]="esterno", + ["nl"]="extern", + ["pe"]="خارجی", + ["ro"]="extern", }, - ["inouteredge"]={ - ["en"]="inouteredge", + ["extremestretch"]={ + ["en"]="extremestretch", + ["fr"]="etirementextreme", }, - ["inoutermargin"]={ - ["en"]="inoutermargin", + ["fact"]={ + ["cs"]="fakt", + ["de"]="gegeben", + ["en"]="fact", + ["fr"]="fait", + ["it"]="fatto", + ["nl"]="gegeven", + ["pe"]="fact", + ["ro"]="fapt", }, - ["inright"]={ - ["cs"]="ivpravo", - ["de"]="imrechten", - ["en"]="inright", - ["fr"]="dansdroit", - ["it"]="indestra", - ["nl"]="inrechter", - ["pe"]="درون‌راست", - ["ro"]="indreapta", + ["february"]={ + ["cs"]="unor", + ["de"]="februar", + ["en"]="february", + ["fr"]="fevrier", + ["it"]="febbraio", + ["nl"]="februari", + ["pe"]="فوریه", + ["ro"]="februarie", }, - ["inrightedge"]={ - ["cs"]="napravo", - ["de"]="imrechtenrand", - ["en"]="inrightedge", - ["fr"]="dansborddroit", - ["it"]="inlatodestro", - ["nl"]="inrechterrand", - ["pe"]="درلبه‌راست", - ["ro"]="inparteadreapta", + ["field"]={ + ["en"]="field", + ["fr"]="champ", + ["nl"]="veld", + }, + ["figure"]={ + ["cs"]="obrazek", + ["de"]="abbildung", + ["en"]="figure", + ["fr"]="figure", + ["it"]="figura", + ["nl"]="figuur", + ["pe"]="شکل", + ["ro"]="figura", }, - ["inrightmargin"]={ - ["cs"]="napravyokraj", - ["de"]="inrechtermarginale", - ["en"]="inrightmargin", - ["fr"]="dansmargedroite", - ["it"]="inmarginedestro", - ["nl"]="inrechtermarge", - ["pe"]="درحاشیه‌راست", - ["ro"]="inmargineadreapta", + ["figures"]={ + ["cs"]="obrazky", + ["de"]="abbildungen", + ["en"]="figures", + ["fr"]="figures", + ["it"]="figure", + ["nl"]="figuren", + ["pe"]="شکلها", + ["ro"]="figure", }, - ["integral"]={ - ["en"]="integral", + ["file"]={ + ["cs"]="soubor", + ["de"]="datei", + ["en"]="file", + ["fr"]="fichier", + ["it"]="file", + ["nl"]="file", + ["pe"]="پرونده", + ["ro"]="fisier", }, - ["interaction"]={ - ["cs"]="interakce", - ["de"]="interaktion", - ["en"]="interaction", - ["fr"]="interaction", - ["it"]="interazione", - ["nl"]="interactie", - ["pe"]="پانل", - ["ro"]="interactiune", + ["final"]={ + ["cs"]="finalni", + ["de"]="endfassung", + ["en"]="final", + ["fr"]="final", + ["it"]="finale", + ["nl"]="definitief", + ["pe"]="نهایی", + ["ro"]="final", }, - ["interactionmenu"]={ - ["cs"]="interaktivnimenu", - ["de"]="interaktionsmenue", - ["en"]="interactionmenu", - ["fr"]="menuinteraction", - ["it"]="menuinterattivo", - ["nl"]="interactiemenu", - ["pe"]="منوی‌پانل", - ["ro"]="meniuinteractiune", + ["first"]={ + ["cs"]="prvni", + ["de"]="erste", + ["en"]="first", + ["fr"]="premier", + ["it"]="primo", + ["nl"]="eerste", + ["pe"]="اولی", + ["ro"]="primul", }, - ["interactive"]={ - ["en"]="interactive", + ["firstcolumn"]={ + ["cs"]="firstcolumn", + ["de"]="firstcolumn", + ["en"]="firstcolumn", + ["fr"]="premierecolonne", + ["it"]="firstcolumn", + ["nl"]="eerstekolom", + ["pe"]="ستون‌اول", + ["ro"]="firstcolumn", }, - ["intermezzi"]={ - ["cs"]="intermezzi", - ["de"]="intermezzi", - ["en"]="intermezzi", - ["fr"]="intermezzi", - ["it"]="intermezzi", - ["nl"]="intermezzos", - ["pe"]="میان‌پرده‌ها", - ["ro"]="intermezzi", + ["firstpage"]={ + ["cs"]="prvnistranka", + ["de"]="ersteseite", + ["en"]="firstpage", + ["fr"]="premierepage", + ["it"]="primapagina", + ["nl"]="eerstepagina", + ["pe"]="صفحه‌اول", + ["ro"]="primapagina", }, - ["intermezzo"]={ - ["cs"]="intermezzo", - ["de"]="intermezzo", - ["en"]="intermezzo", - ["fr"]="intermezzo", - ["it"]="intermezzo", - ["nl"]="intermezzo", - ["pe"]="میان‌پرده", - ["ro"]="intermezzo", + ["firstsubpage"]={ + ["cs"]="prvnipodstranka", + ["de"]="ersteunterseite", + ["en"]="firstsubpage", + ["fr"]="premieresouspage", + ["it"]="primasottopagina", + ["nl"]="eerstesubpagina", + ["pe"]="زیرصفحه‌اول", + ["ro"]="primasubpagina", }, - ["intext"]={ - ["cs"]="dotextu", - ["de"]="imtext", - ["en"]="intext", - ["fr"]="danstexte", - ["it"]="intesto", - ["nl"]="intekst", - ["pe"]="درون‌متن", - ["ro"]="intext", + ["fit"]={ + ["cs"]="prizpusobive", + ["de"]="passend", + ["en"]="fit", + ["fr"]="adapter", + ["it"]="adatta", + ["nl"]="passend", + ["pe"]="پرکردن", + ["ro"]="ajustat", }, - ["headintext"]={ - ["en"]="headintext", - ["nl"]="kopintekst", + ["five"]={ + ["cs"]="pet", + ["de"]="fuenf", + ["en"]="five", + ["fr"]="cinq", + ["it"]="cinque", + ["nl"]="vijf", + ["pe"]="پنج", + ["ro"]="cinci", }, - ["intro"]={ - ["cs"]="uvod", - ["de"]="intro", - ["en"]="intro", - ["fr"]="intro", - ["it"]="intro", - ["nl"]="intro", - ["pe"]="پیشگفتار", - ["ro"]="intro", + ["fix"]={ + ["cs"]="fixuj", + ["de"]="stellewiederher", + ["en"]="fix", + ["fr"]="fix", + ["it"]="fisso", + ["nl"]="herstel", + ["pe"]="ثابت‌کن", + ["ro"]="fix", }, - ["italic"]={ - ["cs"]="kurziva", - ["de"]="italic", - ["en"]="italic", - ["fr"]="italique", - ["it"]="corsivo", - ["nl"]="italic", - ["pe"]="ایتالیک", - ["ro"]="italic", + ["fixed"]={ + ["cs"]="fixne", + ["de"]="fest", + ["en"]="fixed", + ["fr"]="fixe", + ["it"]="fisso", + ["nl"]="vast", + ["pe"]="ثابت", + ["ro"]="fixat", }, - ["italicbold"]={ - ["cs"]="kurzivnitucne", - ["de"]="italicfett", - ["en"]="italicbold", - ["fr"]="grasitalique", - ["it"]="corsivograssetto", - ["nl"]="italicvet", - ["pe"]="مشکی‌ایتالیک", - ["ro"]="italicaldin", + ["flexible"]={ + ["cs"]="prizpusobive", + ["de"]="flexibel", + ["en"]="flexible", + ["fr"]="flexible", + ["it"]="flessibile", + ["nl"]="flexibel", + ["pe"]="انعطافپذیر", + ["ro"]="flexibil", }, - ["item"]={ - ["cs"]="polozka", - ["de"]="pos", - ["en"]="item", - ["fr"]="element", - ["it"]="elemento", - ["nl"]="som", - ["pe"]="آیتم", - ["ro"]="element", + ["float"]={ + ["cs"]="plvouciobjekt", + ["de"]="gleitobjekt", + ["en"]="float", + ["fr"]="flottant", + ["it"]="oggettomobile", + ["nl"]="blok", + ["pe"]="شناور", + ["ro"]="obiectmobil", }, - ["itemize"]={ - ["cs"]="vycet", - ["de"]="aufzaehlung", - ["en"]="itemize", - ["fr"]="lister", - ["it"]="elenco", - ["nl"]="opsomming", - ["pe"]="آیتم‌بندی", - ["ro"]="enumerare", + ["flushinner"]={ + ["cs"]="flushinner", + ["de"]="flushinner", + ["en"]="flushinner", + ["fr"]="alignerinterieur", + ["it"]="flushinner", + ["nl"]="lijnbinnen", + ["pe"]="پمپ‌داخلی", + ["ro"]="flushinner", }, - ["its"]={ - ["cs"]="pol", - ["de"]="its", - ["en"]="its", - ["fr"]="its", - ["it"]="its", - ["nl"]="its", - ["pe"]="آیم", - ["ro"]="propriu", + ["flushleft"]={ + ["cs"]="flushleft", + ["de"]="flushleft", + ["en"]="flushleft", + ["fr"]="alignergauche", + ["it"]="flushleft", + ["nl"]="lijnlinks", + ["pe"]="پمپ‌چپ", + ["ro"]="flushleft", + }, + ["flushouter"]={ + ["cs"]="flushouter", + ["de"]="flushouter", + ["en"]="flushouter", + ["fr"]="alignerexterieur", + ["it"]="flushouter", + ["nl"]="lijnbuiten", + ["pe"]="پمپ‌خارجی", + ["ro"]="flushouter", }, - ["january"]={ - ["cs"]="leden", - ["de"]="januar", - ["en"]="january", - ["fr"]="janvier", - ["it"]="gennaio", - ["nl"]="januari", - ["pe"]="ژانویه", - ["ro"]="ianuarie", + ["flushright"]={ + ["cs"]="flushright", + ["de"]="flushright", + ["en"]="flushright", + ["fr"]="alignerdroite", + ["it"]="flushright", + ["nl"]="lijnrechts", + ["pe"]="پمپ‌راست", + ["ro"]="flushright", }, - ["joinedup"]={ - ["cs"]="spojeno", - ["de"]="keinabstand", - ["en"]="joinedup", - ["fr"]="joinedup", - ["it"]="unito", - ["nl"]="aansluitend", - ["pe"]="متصل‌بالا", - ["ro"]="unit", + ["followingpage"]={ + ["en"]="followingpage", + ["fr"]="pagesuccesseur", + ["nl"]="opvolgendepagina", }, - ["notjoinedup"]={ - ["en"]="notjoinedup", - ["nl"]="nietaansluitend", + ["footer"]={ + ["cs"]="upati", + ["de"]="fusszeile", + ["en"]="footer", + ["fr"]="pdp", + ["it"]="piedipagina", + ["nl"]="voet", + ["pe"]="ته‌برگ", + ["ro"]="subsol", }, - ["july"]={ - ["cs"]="cervenec", - ["de"]="juli", - ["en"]="july", - ["fr"]="juillet", - ["it"]="luglio", - ["nl"]="juli", - ["pe"]="ژولای", - ["ro"]="iulie", + ["footnote"]={ + ["cs"]="poznamkapodcarou", + ["de"]="fussnote", + ["en"]="footnote", + ["fr"]="notebdp", + ["it"]="notapdp", + ["nl"]="voetnoot", + ["pe"]="پانوشت", + ["ro"]="notasubsol", }, - ["june"]={ - ["cs"]="cerven", - ["de"]="juni", - ["en"]="june", - ["fr"]="juin", - ["it"]="giugno", - ["nl"]="juni", - ["pe"]="ژوئن", - ["ro"]="iunie", + ["force"]={ + ["cs"]="sila", + ["de"]="zwinge", + ["en"]="force", + ["fr"]="forcer", + ["it"]="forza", + ["nl"]="forceer", + ["pe"]="اجبار", + ["ro"]="fortat", }, - ["keep"]={ - ["cs"]="drzet", - ["de"]="behalte", - ["en"]="keep", - ["fr"]="maintient", - ["it"]="mantieni", - ["nl"]="handhaaf", - ["pe"]="نگهدار", - ["ro"]="mentine", + ["foreground"]={ + ["cs"]="popredi", + ["de"]="vordergrund", + ["en"]="foreground", + ["fr"]="premierplan", + ["it"]="foreground", + ["nl"]="voorgrond", + ["pe"]="پیش‌زمینه", + ["ro"]="primplan", }, - ["kerncharacters"]={ - ["en"]="kerncharacters", + ["formula"]={ + ["cs"]="rovnice", + ["de"]="formel", + ["en"]="formula", + ["fr"]="formule", + ["it"]="formula", + ["nl"]="formule", + ["pe"]="فرمول", + ["ro"]="formula", }, - ["knockout"]={ - ["cs"]="knockout", - ["de"]="knockout", - ["en"]="knockout", - ["fr"]="knockout", - ["it"]="knockout", - ["nl"]="knockout", - ["pe"]="knockout", - ["ro"]="knockout", + ["formulas"]={ + ["cs"]="rovnice", + ["de"]="formeln", + ["en"]="formulas", + ["fr"]="formules", + ["it"]="formule", + ["nl"]="formules", + ["pe"]="فرمولها", + ["ro"]="formule", }, - ["label"]={ - ["cs"]="popisek", - ["de"]="label", - ["en"]="label", - ["fr"]="etiquette", - ["it"]="etichetta", - ["nl"]="label", - ["pe"]="برچسب", - ["ro"]="eticheta", + ["forward"]={ + ["cs"]="vpred", + ["de"]="vorwaerts", + ["en"]="forward", + ["fr"]="enavant", + ["it"]="avanti", + ["nl"]="vooruit", + ["pe"]="به‌جلو", + ["ro"]="avans", }, - ["landscape"]={ - ["cs"]="nasirku", - ["de"]="querformat", - ["en"]="landscape", - ["fr"]="paysage", - ["it"]="orizzontale", - ["nl"]="liggend", - ["pe"]="صفحه‌گسترده", - ["ro"]="vedere", + ["four"]={ + ["cs"]="ctyri", + ["de"]="vier", + ["en"]="four", + ["fr"]="quatre", + ["it"]="quattro", + ["nl"]="vier", + ["pe"]="چهار", + ["ro"]="patru", }, - ["last"]={ - ["cs"]="posledni", - ["de"]="letzte", - ["en"]="last", - ["fr"]="dernier", - ["it"]="ultimo", - ["nl"]="laatste", - ["pe"]="آخرین", - ["ro"]="ultim", + ["fractions"]={ + ["en"]="fractions", + ["fr"]="fractions", }, - ["lastcolumn"]={ - ["cs"]="lastcolumn", - ["de"]="lastcolumn", - ["en"]="lastcolumn", - ["fr"]="dernierecolonne", - ["it"]="lastcolumn", - ["nl"]="laatstekolom", - ["pe"]="آخرین‌ستون", - ["ro"]="lastcolumn", + ["frame"]={ + ["cs"]="ramecek", + ["de"]="rahmen", + ["en"]="frame", + ["fr"]="cadre", + ["it"]="cornice", + ["nl"]="kader", + ["pe"]="قالب", + ["ro"]="incadrat", }, - ["lastpage"]={ - ["cs"]="poslednistrana", - ["de"]="letzteseite", - ["en"]="lastpage", - ["fr"]="dernierepage", - ["it"]="ultimapagina", - ["nl"]="laatstepagina", - ["pe"]="صفحه‌آخر", - ["ro"]="ultimapagina", + ["framedtext"]={ + ["cs"]="oramovanytext", + ["de"]="umrahmtertext", + ["en"]="framedtext", + ["fr"]="texteencadre", + ["it"]="testoincorniciato", + ["nl"]="kadertekst", + ["pe"]="متن‌قالبی", + ["ro"]="textinconjurat", }, - ["lastpagenumber"]={ - ["cs"]="lastpagenumber", - ["de"]="lastpagenumber", - ["en"]="lastpagenumber", - ["fr"]="derniernumeropage", - ["it"]="lastpagenumber", - ["nl"]="laatstepaginanummer", - ["pe"]="شماه‌صفحه‌آخر", - ["ro"]="lastpagenumber", + ["friday"]={ + ["cs"]="patek", + ["de"]="freitag", + ["en"]="friday", + ["fr"]="vendredi", + ["it"]="venerdi", + ["nl"]="vrijdag", + ["pe"]="جمعه", + ["ro"]="vineri", }, - ["lastsubpage"]={ - ["cs"]="poslaednipodstranka", - ["de"]="letzteunterseite", - ["en"]="lastsubpage", - ["fr"]="dernieresouspage", - ["it"]="ultimasottopagina", - ["nl"]="laatstesubpagina", - ["pe"]="زیرصفحه‌آخر", - ["ro"]="ultimasubpagina", + ["frontmatter"]={ + ["cs"]="prednicasti", + ["de"]="einleitungen", + ["en"]="frontmatter", + ["fr"]="pagesliminaires", + ["it"]="preambolo", + ["nl"]="inleidingen", + ["pe"]="پیش‌مطلب", + ["ro"]="prologul", }, - ["layer"]={ - ["cs"]="layer", - ["de"]="layer", - ["en"]="layer", - ["fr"]="layer", - ["it"]="layer", - ["nl"]="layer", - ["pe"]="layer", - ["ro"]="layer", + ["frontpart"]={ + ["cs"]="prednicast", + ["de"]="einleitung", + ["en"]="frontpart", + ["fr"]="preface", + ["it"]="prefazione", + ["nl"]="inleiding", + ["pe"]="پیش‌قسمت", + ["ro"]="prolog", + }, + ["fullhz"]={ + ["cs"]="fullhz", + ["de"]="fullhz", + ["en"]="fullhz", + ["fr"]="hzcomplet", + ["it"]="fullhz", + ["nl"]="fullenhz", + ["pe"]="fullhz", + ["ro"]="fullhz", }, - ["left"]={ - ["cs"]="vlevo", - ["de"]="links", - ["en"]="left", - ["fr"]="gauche", - ["it"]="sinistra", - ["nl"]="links", - ["pe"]="چپ", - ["ro"]="stanga", + ["global"]={ + ["cs"]="globalne", + ["de"]="global", + ["en"]="global", + ["fr"]="global", + ["it"]="globale", + ["nl"]="globaal", + ["pe"]="سراسری", + ["ro"]="global", }, - ["leftedge"]={ - ["cs"]="levahrana", - ["de"]="linkekante", - ["en"]="leftedge", - ["fr"]="bordgauche", - ["it"]="bordosinistro", - ["nl"]="linkerrand", - ["pe"]="لبه‌چپ", - ["ro"]="bordurastanga", + ["graphic"]={ + ["cs"]="graf", + ["de"]="grafik", + ["en"]="graphic", + ["fr"]="graphique", + ["it"]="grafico", + ["nl"]="grafiek", + ["pe"]="گرافیک", + ["ro"]="graficul", }, - ["lefthanging"]={ - ["cs"]="lefthanging", - ["de"]="lefthanging", - ["en"]="lefthanging", - ["fr"]="lefthanging", - ["it"]="lefthanging", - ["nl"]="linkshangend", - ["pe"]="آویزان‌چپ", - ["ro"]="lefthanging", + ["graphics"]={ + ["cs"]="grafy", + ["de"]="grafiken", + ["en"]="graphics", + ["fr"]="graphiques", + ["it"]="grafici", + ["nl"]="grafieken", + ["pe"]="گرافیکها", + ["ro"]="graficele", }, - ["leftmargin"]={ - ["cs"]="levyokraj", - ["de"]="linkerrand", - ["en"]="leftmargin", - ["fr"]="margegauche", - ["it"]="marginesinistro", - ["nl"]="linkermarge", - ["pe"]="حاشیه‌چپ", - ["ro"]="marginestanga", + ["gray"]={ + ["cs"]="seda", + ["de"]="grau", + ["en"]="gray", + ["fr"]="gris", + ["it"]="grigio", + ["nl"]="grijs", + ["pe"]="خاکستری", + ["ro"]="gri", }, - ["leftpage"]={ - ["cs"]="levastranka", - ["de"]="linkerseite", - ["en"]="leftpage", - ["fr"]="pagegauche", - ["it"]="paginasinistra", - ["nl"]="linkerpagina", - ["pe"]="صفحه‌چپ", - ["ro"]="paginastanga", + ["greek"]={ + ["cs"]="recky", + ["de"]="griechisch", + ["en"]="greek", + ["fr"]="grec", + ["it"]="greco", + ["nl"]="grieks", + ["pe"]="یونانی", + ["ro"]="grec", }, - ["lefttoright"]={ - ["cs"]="lefttoright", - ["de"]="lefttoright", - ["en"]="lefttoright", - ["fr"]="lefttoright", - ["it"]="lefttoright", - ["nl"]="lefttoright", - ["pe"]="lefttoright", - ["ro"]="lefttoright", + ["grid"]={ + ["cs"]="mrizka", + ["de"]="gritter", + ["en"]="grid", + ["fr"]="grille", + ["it"]="griglia", + ["nl"]="grid", + ["pe"]="توری", + ["ro"]="grila", }, - ["legend"]={ - ["cs"]="legenda", - ["de"]="legende", - ["en"]="legend", - ["fr"]="legende", - ["it"]="legenda", - ["nl"]="legenda", - ["pe"]="راهنما", - ["ro"]="legenda", + ["halfline"]={ + ["cs"]="pulradku", + ["de"]="halbezeile", + ["en"]="halfline", + ["fr"]="demiligne", + ["it"]="mezzariga", + ["nl"]="halveregel", + ["pe"]="نیم‌خط", + ["ro"]="jumatatelinie", }, - ["less"]={ - ["en"]="less", - ["nl"]="minder", + ["handwritten"]={ + ["cs"]="rukopisne", + ["de"]="handschrift", + ["en"]="handwritten", + ["fr"]="manuscript", + ["it"]="grafiamanuale", + ["nl"]="handschrift", + ["pe"]="دست‌نوشته", + ["ro"]="scrismanual", }, - ["lesshyphenation"]={ - ["cs"]="lesshyphenation", - ["de"]="lesshyphenation", - ["en"]="lesshyphenation", - ["fr"]="lesshyphenation", - ["it"]="lesshyphenation", - ["nl"]="lesshyphenation", - ["pe"]="شکست‌کلمات‌کمتر", - ["ro"]="lesshyphenation", + ["hang"]={ + ["cs"]="zaveseni", + ["de"]="haengend", + ["en"]="hang", + ["fr"]="suspendre", + ["it"]="sospendi", + ["nl"]="hang", + ["pe"]="بیاویز", + ["ro"]="suspenda", }, - ["letterspacing"]={ - ["en"]="letterspacing", + ["hanging"]={ + ["cs"]="visici", + ["de"]="haengend", + ["en"]="hanging", + ["fr"]="suspension", + ["it"]="sospeso", + ["nl"]="hangend", + ["pe"]="آویزان", + ["ro"]="suspendat", }, - ["line"]={ - ["cs"]="radek", - ["de"]="zeile", - ["en"]="line", - ["fr"]="ligne", - ["it"]="riga", - ["nl"]="regel", - ["pe"]="خط", - ["ro"]="linie", + ["hangingboth"]={ + ["en"]="hangingboth", + ["fr"]="suspensionchacun", + ["nl"]="beidehangend", }, - ["linenote"]={ - ["cs"]="linenote", - ["de"]="linenote", - ["en"]="linenote", - ["fr"]="noteligne", - ["it"]="linenote", - ["nl"]="regelnoot", - ["pe"]="خط‌نوشت", - ["ro"]="linenote", + ["head"]={ + ["cs"]="hlavicka", + ["de"]="kopf", + ["en"]="head", + ["fr"]="tete", + ["it"]="testa", + ["nl"]="kop", + ["pe"]="سر", + ["ro"]="antet", }, - ["lines"]={ - ["cs"]="radky", - ["de"]="zeilen", - ["en"]="lines", - ["fr"]="lignes", - ["it"]="righe", - ["nl"]="regels", - ["pe"]="خطها", - ["ro"]="linii", + ["header"]={ + ["cs"]="zahlavi", + ["de"]="kopfzeile", + ["en"]="header", + ["fr"]="entête", + ["it"]="intestazione", + ["nl"]="hoofd", + ["pe"]="سربرگ", + ["ro"]="antet", }, - ["linked"]={ - ["en"]="linked", + ["headintext"]={ + ["en"]="headintext", + ["fr"]="tetedanstexte", + ["nl"]="kopintekst", }, - ["list"]={ - ["cs"]="seznam", - ["de"]="liste", - ["en"]="list", - ["fr"]="liste", - ["it"]="elenco", - ["nl"]="lijst", - ["pe"]="لیست", - ["ro"]="lista", + ["height"]={ + ["cs"]="vyska", + ["de"]="hoehe", + ["en"]="height", + ["fr"]="hauteur", + ["it"]="altezza", + ["nl"]="hoogte", + ["pe"]="ارتفاع", + ["ro"]="inaltime", }, - ["local"]={ - ["cs"]="lokalne", - ["de"]="lokal", - ["en"]="local", - ["fr"]="local", - ["it"]="locale", - ["nl"]="lokaal", - ["pe"]="موضعی", - ["ro"]="local", + ["helptext"]={ + ["cs"]="textnapovedy", + ["de"]="hilfetext", + ["en"]="helptext", + ["fr"]="texteaide", + ["it"]="testoaiuto", + ["nl"]="helptekst", + ["pe"]="متن‌کمکی", + ["ro"]="textajutator", }, - ["localenvironment"]={ - ["cs"]="lokalnihoprostredi", - ["de"]="lokaleumgebung", - ["en"]="localenvironment", - ["fr"]="environementlocal", - ["it"]="ambientelocale", - ["nl"]="deelomgeving", - ["pe"]="محیط‌موضعی", - ["ro"]="mediulocal", + ["hencefore"]={ + ["cs"]="vyse", + ["de"]="vorher", + ["en"]="hencefore", + ["fr"]="precedemment", + ["it"]="precedente", + ["nl"]="hierboven", + ["pe"]="hencefore", + ["ro"]="precedent", }, - ["logo"]={ - ["cs"]="logo", - ["de"]="logo", - ["en"]="logo", - ["fr"]="logo", - ["it"]="logo", - ["nl"]="logo", - ["pe"]="آرم", - ["ro"]="logo", + ["here"]={ + ["cs"]="zde", + ["de"]="hier", + ["en"]="here", + ["fr"]="ici", + ["it"]="qui", + ["nl"]="hier", + ["pe"]="اینجا", + ["ro"]="aici", }, - ["logos"]={ - ["cs"]="loga", - ["de"]="logos", - ["en"]="logos", - ["fr"]="logos", - ["it"]="loghi", - ["nl"]="logos", - ["pe"]="آرمها", - ["ro"]="logos", + ["hereafter"]={ + ["cs"]="nize", + ["de"]="nachher", + ["en"]="hereafter", + ["fr"]="ciapres", + ["it"]="seguente", + ["nl"]="hieronder", + ["pe"]="ازاین‌به‌بعد", + ["ro"]="urmator", }, - ["lohi"]={ - ["cs"]="nivy", - ["de"]="hoti", - ["en"]="lohi", - ["fr"]="baha", - ["it"]="pedap", - ["nl"]="laho", - ["pe"]="پابا", - ["ro"]="lohi", + ["hidden"]={ + ["cs"]="skryte", + ["de"]="versteckt", + ["en"]="hidden", + ["fr"]="cache", + ["it"]="nascosto", + ["nl"]="verborgen", + ["pe"]="پنهانی", + ["ro"]="ascuns", }, - ["long"]={ - ["en"]="long", + ["hiddenbar"]={ + ["en"]="hiddenbar", + ["fr"]="barrecachee", }, - ["loose"]={ - ["cs"]="uvolnene", - ["de"]="lose", - ["en"]="loose", - ["fr"]="perte", - ["it"]="lento", - ["nl"]="los", - ["pe"]="شل", - ["ro"]="larg", + ["hiding"]={ + ["cs"]="skryt", + ["de"]="verbergen", + ["en"]="hiding", + ["fr"]="encachant", + ["it"]="nascondere", + ["nl"]="verbergen", + ["pe"]="پنهان‌کردن", + ["ro"]="ascundere", }, - ["low"]={ - ["cs"]="nizko", - ["de"]="tief", - ["en"]="low", - ["fr"]="bas", - ["it"]="basso", - ["nl"]="laag", - ["pe"]="پایین", - ["ro"]="jos", + ["high"]={ + ["cs"]="vysoko", + ["de"]="hoch", + ["en"]="high", + ["fr"]="exp", + ["it"]="alto", + ["nl"]="hoog", + ["pe"]="بلند", + ["ro"]="inalt", }, - ["ls"]={ - ["cs"]="ls", - ["de"]="ls", - ["en"]="ls", - ["fr"]="ls", - ["it"]="ls", - ["nl"]="ls", - ["pe"]="ls", - ["ro"]="ls", + ["horizontal"]={ + ["cs"]="horizontalne", + ["de"]="horizontal", + ["en"]="horizontal", + ["fr"]="horizontal", + ["it"]="orizzontale", + ["nl"]="horizontaal", + ["pe"]="افقی", + ["ro"]="orizontal", }, - ["makeup"]={ - ["cs"]="zlom", - ["de"]="umbruch", - ["en"]="makeup", - ["fr"]="makeup", - ["it"]="makeup", - ["nl"]="opmaak", - ["pe"]="آرایش", - ["ro"]="marcaj", + ["hyphenated"]={ + ["cs"]="hyphenated", + ["de"]="hyphenate", + ["en"]="hyphenated", + ["fr"]="aveccesure", + ["it"]="sillabato", + ["nl"]="afgebroken", + ["pe"]="شکسته", + ["ro"]="despsilabe", }, - ["mar"]={ - ["cs"]="mar", - ["de"]="mar", - ["en"]="mar", - ["fr"]="mar", - ["it"]="mar", - ["nl"]="mar", - ["pe"]="حاش", - ["ro"]="mar", + ["hz"]={ + ["cs"]="hz", + ["de"]="hz", + ["en"]="hz", + ["fr"]="hz", + ["it"]="hz", + ["nl"]="hz", + ["pe"]="hz", + ["ro"]="hz", }, - ["march"]={ - ["cs"]="brezen", - ["de"]="maerz", - ["en"]="march", - ["fr"]="mars", - ["it"]="marzo", - ["nl"]="maart", - ["pe"]="مارس", - ["ro"]="martie", + ["inbetween"]={ + ["cs"]="mezi", + ["de"]="zwischen", + ["en"]="inbetween", + ["fr"]="entre", + ["it"]="tra", + ["nl"]="tussen", + ["pe"]="دربین", + ["ro"]="intre", }, - ["margin"]={ - ["cs"]="marginalie", - ["de"]="marginalie", - ["en"]="margin", - ["fr"]="marge", - ["it"]="margine", - ["nl"]="marge", - ["pe"]="حاشیه", - ["ro"]="margine", + ["index"]={ + ["cs"]="rejstrik", + ["de"]="index", + ["en"]="index", + ["fr"]="index", + ["it"]="indiceanalitico", + ["nl"]="index", + ["pe"]="نمایه", + ["ro"]="index", }, - ["marginedge"]={ - ["cs"]="textovahrana", - ["de"]="marginalkante", - ["en"]="marginedge", - ["fr"]="bordmarge", - ["it"]="bordomargine", - ["nl"]="kantlijn", - ["pe"]="لبه‌حاشیه", - ["ro"]="marginebordura", + ["indices"]={ + ["cs"]="rejstriky", + ["de"]="indizies", + ["en"]="indices", + ["fr"]="indices", + ["it"]="indicianalitici", + ["nl"]="indices", + ["pe"]="نمایه‌ها", + ["ro"]="indexuri", }, - ["margintext"]={ - ["cs"]="marginalnitext", - ["de"]="marginaltext", - ["en"]="margintext", - ["fr"]="textemarge", - ["it"]="testoinmargine", - ["nl"]="margetekst", - ["pe"]="متن‌حاشیه", - ["ro"]="textmarginal", + ["inherit"]={ + ["cs"]="inherit", + ["de"]="inherit", + ["en"]="inherit", + ["fr"]="heriter", + ["it"]="inherit", + ["nl"]="erf", + ["pe"]="ارث‌بردن", + ["ro"]="inherit", }, - ["margintitle"]={ - ["cs"]="titulmarginalie", - ["de"]="marginaltitel", - ["en"]="margintitle", - ["fr"]="titremarge", - ["it"]="titoloinmargine", - ["nl"]="margetitel", - ["pe"]="عنوان‌حاشیه", - ["ro"]="titlumarginal", + ["ininner"]={ + ["cs"]="ininner", + ["de"]="ininner", + ["en"]="ininner", + ["fr"]="dansinterieur", + ["it"]="ininner", + ["nl"]="inbinnen", + ["pe"]="درداخلی", + ["ro"]="ininner", }, - ["marking"]={ - ["cs"]="znaceni", - ["de"]="beschriftung", - ["en"]="marking", - ["fr"]="marquage", - ["it"]="marcatura", - ["nl"]="markering", - ["pe"]="نشانه‌گذاری", - ["ro"]="marcaje", + ["ininneredge"]={ + ["en"]="ininneredge", + ["fr"]="dansbordinterieur", }, - ["math"]={ - ["en"]="math", + ["ininnermargin"]={ + ["en"]="ininnermargin", + ["fr"]="dansmargeinterieure", }, - ["mathalignment"]={ - ["cs"]="mathalignment", - ["de"]="mathalignment", - ["en"]="mathalignment", - ["fr"]="mathalignment", - ["it"]="mathalignment", - ["nl"]="wiskundeuitlijnen", - ["pe"]="تنظیم‌ریاضی", - ["ro"]="mathalignment", + ["inleft"]={ + ["cs"]="ivlevo", + ["de"]="imlinken", + ["en"]="inleft", + ["fr"]="dansgauche", + ["it"]="insinistra", + ["nl"]="inlinker", + ["pe"]="درون‌چپ", + ["ro"]="instanga", }, - ["mathcases"]={ - ["cs"]="mathcases", - ["de"]="mathcases", - ["en"]="mathcases", - ["fr"]="mathcases", - ["it"]="mathcases", - ["nl"]="mathcases", - ["pe"]="حالتهای‌ریاضی", - ["ro"]="mathcases", + ["inleftedge"]={ + ["cs"]="nalevo", + ["de"]="imlinkenrand", + ["en"]="inleftedge", + ["fr"]="dansbordgauche", + ["it"]="inlatosinistro", + ["nl"]="inlinkerrand", + ["pe"]="درلبه‌چپ", + ["ro"]="inparteastanga", }, - ["mathematics"]={ - ["cs"]="mathematika", - ["de"]="mathematik", - ["en"]="mathematics", - ["fr"]="mathematique", - ["it"]="matematica", - ["nl"]="wiskunde", - ["pe"]="ریاضی", - ["ro"]="matematica", + ["inleftmargin"]={ + ["cs"]="nalevyokraj", + ["de"]="inlinkermarginale", + ["en"]="inleftmargin", + ["fr"]="dansmargegauche", + ["it"]="inmarginesinistro", + ["nl"]="inlinkermarge", + ["pe"]="درحاشیه‌چپ", + ["ro"]="inmargineastanga", }, - ["mathmatrix"]={ - ["cs"]="mathmatrix", - ["de"]="mathmatrix", - ["en"]="mathmatrix", - ["fr"]="mathmatrix", - ["it"]="mathmatrix", - ["nl"]="wiskundematrix", - ["pe"]="ماتریش‌ریاضی", - ["ro"]="mathmatrix", + ["inline"]={ + ["en"]="inline", + ["fr"]="enligne", }, - ["max"]={ - ["cs"]="max", - ["de"]="max", - ["en"]="max", - ["fr"]="max", - ["it"]="max", - ["nl"]="max", - ["pe"]="بیشترین", - ["ro"]="max", + ["inmargin"]={ + ["cs"]="naokraji", + ["de"]="imrand", + ["en"]="inmargin", + ["fr"]="dansmarge", + ["it"]="inmargine", + ["nl"]="inmarge", + ["pe"]="درون‌حاشیه", + ["ro"]="inmargine", }, - ["maxdepth"]={ - ["en"]="maxdepth", - ["nl"]="maxdiepte", + ["inner"]={ + ["cs"]="uvnitr", + ["de"]="innen", + ["en"]="inner", + ["fr"]="interieur", + ["it"]="interno", + ["nl"]="binnen", + ["pe"]="داخلی", + ["ro"]="intern", }, - ["maxheight"]={ - ["en"]="maxheight", - ["nl"]="maxhoogte", + ["inneredge"]={ + ["cs"]="inneredge", + ["de"]="inneredge", + ["en"]="inneredge", + ["fr"]="bordinterieur", + ["it"]="bordointerno", + ["nl"]="binnenrand", + ["pe"]="لبه‌داخلی", + ["ro"]="inneredge", }, - ["maxwidth"]={ - ["en"]="maxwidth", - ["nl"]="maxbreedte", + ["innermargin"]={ + ["cs"]="innermargin", + ["de"]="innermargin", + ["en"]="innermargin", + ["fr"]="margeinterieure", + ["it"]="margineinterno", + ["nl"]="binnenmarge", + ["pe"]="حاشیه‌داخلی", + ["ro"]="innermargin", }, - ["may"]={ - ["cs"]="kveten", - ["de"]="mai", - ["en"]="may", - ["fr"]="mai", - ["it"]="maggio", - ["nl"]="mei", - ["pe"]="مه", - ["ro"]="mai", + ["inother"]={ + ["cs"]="inother", + ["de"]="inother", + ["en"]="inother", + ["fr"]="dansautre", + ["it"]="inother", + ["nl"]="inandere", + ["pe"]="inother", + ["ro"]="inother", }, - ["mediaeval"]={ - ["cs"]="stredoveky", - ["de"]="mittelalterlich", - ["en"]="mediaeval", - ["fr"]="medieval", - ["it"]="medievale", - ["nl"]="mediaeval", - ["pe"]="mediaeval", - ["ro"]="medieval", + ["inouter"]={ + ["cs"]="inouter", + ["de"]="inouter", + ["en"]="inouter", + ["fr"]="dansexterieur", + ["it"]="inouter", + ["nl"]="inbuiten", + ["pe"]="درخارجی", + ["ro"]="inouter", }, - ["medium"]={ - ["cs"]="stredni", - ["de"]="mittel", - ["en"]="medium", - ["fr"]="moyen", - ["it"]="medio", - ["nl"]="middel", - ["pe"]="متوسط", - ["ro"]="mediu", + ["inouteredge"]={ + ["en"]="inouteredge", + ["fr"]="dansbordexterieur", }, - ["middle"]={ - ["cs"]="nastred", - ["de"]="mittig", - ["en"]="middle", - ["fr"]="milieu", - ["it"]="centro", - ["nl"]="midden", - ["pe"]="میان", - ["ro"]="centru", + ["inoutermargin"]={ + ["en"]="inoutermargin", + ["fr"]="dansmargeexterieure", }, - ["min"]={ - ["cs"]="min", - ["de"]="min", - ["en"]="min", - ["fr"]="min", - ["it"]="min", - ["nl"]="min", - ["pe"]="کمترین", - ["ro"]="min", + ["inright"]={ + ["cs"]="ivpravo", + ["de"]="imrechten", + ["en"]="inright", + ["fr"]="dansdroite", + ["it"]="indestra", + ["nl"]="inrechter", + ["pe"]="درون‌راست", + ["ro"]="indreapta", }, - ["mindepth"]={ - ["en"]="mindepth", - ["nl"]="mindiepte", + ["inrightedge"]={ + ["cs"]="napravo", + ["de"]="imrechtenrand", + ["en"]="inrightedge", + ["fr"]="dansborddroit", + ["it"]="inlatodestro", + ["nl"]="inrechterrand", + ["pe"]="درلبه‌راست", + ["ro"]="inparteadreapta", }, - ["minheight"]={ - ["cs"]="minvyska", - ["de"]="minhoehe", - ["en"]="minheight", - ["fr"]="hauteurmin", - ["it"]="altezzamin", - ["nl"]="minhoogte", - ["pe"]="کمترین‌ارتفاع", - ["ro"]="inaltimeminima", + ["inrightmargin"]={ + ["cs"]="napravyokraj", + ["de"]="inrechtermarginale", + ["en"]="inrightmargin", + ["fr"]="dansmargedroite", + ["it"]="inmarginedestro", + ["nl"]="inrechtermarge", + ["pe"]="درحاشیه‌راست", + ["ro"]="inmargineadreapta", }, - ["minwidth"]={ - ["cs"]="minsirka", - ["de"]="minbreite", - ["en"]="minwidth", - ["fr"]="largeurmin", - ["it"]="ampiezzamin", - ["nl"]="minbreedte", - ["pe"]="کمترین‌عرض", - ["ro"]="latimeminima", + ["integral"]={ + ["en"]="integral", + ["fr"]="integrale", }, - ["mirrored"]={ - ["cs"]="zrcadleno", - ["de"]="gespiegelt", - ["en"]="mirrored", - ["fr"]="reflete", - ["it"]="riflesso", - ["nl"]="gespiegeld", - ["pe"]="منعکس", - ["ro"]="oglindit", + ["interaction"]={ + ["cs"]="interakce", + ["de"]="interaktion", + ["en"]="interaction", + ["fr"]="interaction", + ["it"]="interazione", + ["nl"]="interactie", + ["pe"]="پانل", + ["ro"]="interactiune", }, - ["mixed"]={ - ["en"]="mixed", + ["interactionmenu"]={ + ["cs"]="interaktivnimenu", + ["de"]="interaktionsmenue", + ["en"]="interactionmenu", + ["fr"]="menuinteraction", + ["it"]="menuinterattivo", + ["nl"]="interactiemenu", + ["pe"]="منوی‌پانل", + ["ro"]="meniuinteractiune", }, - ["monday"]={ - ["cs"]="pondeli", - ["de"]="montag", - ["en"]="monday", - ["fr"]="lundi", - ["it"]="lunedi", - ["nl"]="maandag", - ["pe"]="دوشنبه", - ["ro"]="luni", + ["interactive"]={ + ["en"]="interactive", + ["fr"]="interactif", }, - ["mono"]={ - ["cs"]="mono", - ["de"]="mono", - ["en"]="mono", - ["fr"]="mono", - ["it"]="mono", - ["nl"]="mono", - ["pe"]="مونو", - ["ro"]="mono", + ["intermezzi"]={ + ["cs"]="intermezzi", + ["de"]="intermezzi", + ["en"]="intermezzi", + ["fr"]="interludes", + ["it"]="intermezzi", + ["nl"]="intermezzos", + ["pe"]="میان‌پرده‌ها", + ["ro"]="intermezzi", }, - ["monobold"]={ - ["cs"]="monotucne", - ["de"]="monofett", - ["en"]="monobold", - ["fr"]="monogras", - ["it"]="monograssetto", - ["nl"]="monovet", - ["pe"]="monobold", - ["ro"]="monoaldin", + ["intermezzo"]={ + ["cs"]="intermezzo", + ["de"]="intermezzo", + ["en"]="intermezzo", + ["fr"]="interlude", + ["it"]="intermezzo", + ["nl"]="intermezzo", + ["pe"]="میان‌پرده", + ["ro"]="intermezzo", }, - ["mononormal"]={ - ["en"]="mononormal", + ["intext"]={ + ["cs"]="dotextu", + ["de"]="imtext", + ["en"]="intext", + ["fr"]="danstexte", + ["it"]="intesto", + ["nl"]="intekst", + ["pe"]="درون‌متن", + ["ro"]="intext", }, - ["month"]={ - ["cs"]="mesic", - ["de"]="monat", - ["en"]="month", - ["fr"]="mois", - ["it"]="mese", - ["nl"]="maand", - ["pe"]="ماه", - ["ro"]="luna", + ["intro"]={ + ["cs"]="uvod", + ["de"]="intro", + ["en"]="intro", + ["fr"]="intro", + ["it"]="intro", + ["nl"]="intro", + ["pe"]="پیشگفتار", + ["ro"]="intro", }, - ["more"]={ - ["en"]="more", - ["nl"]="meer", + ["italic"]={ + ["cs"]="kurziva", + ["de"]="italic", + ["en"]="italic", + ["fr"]="italique", + ["it"]="corsivo", + ["nl"]="italic", + ["pe"]="ایتالیک", + ["ro"]="italic", }, - ["morehyphenation"]={ - ["cs"]="morehyphenation", - ["de"]="morehyphenation", - ["en"]="morehyphenation", - ["fr"]="morehyphenation", - ["it"]="morehyphenation", - ["nl"]="morehyphenation", - ["pe"]="شکست‌کلمات‌بیشتر", - ["ro"]="morehyphenation", + ["italicbold"]={ + ["cs"]="kurzivnitucne", + ["de"]="italicfett", + ["en"]="italicbold", + ["fr"]="italiquegras", + ["it"]="corsivograssetto", + ["nl"]="italicvet", + ["pe"]="مشکی‌ایتالیک", + ["ro"]="italicaldin", }, - ["name"]={ - ["cs"]="jmeno", - ["de"]="name", - ["en"]="name", - ["fr"]="nom", - ["it"]="nome", - ["nl"]="naam", - ["pe"]="نام", - ["ro"]="nume", + ["item"]={ + ["cs"]="polozka", + ["de"]="pos", + ["en"]="item", + ["fr"]="élément", + ["it"]="elemento", + ["nl"]="som", + ["pe"]="آیتم", + ["ro"]="element", }, - ["narrow"]={ - ["cs"]="uzky", - ["de"]="schmall", - ["en"]="narrow", - ["fr"]="etroit", - ["it"]="stretto", - ["nl"]="smal", - ["pe"]="نازک", - ["ro"]="ingust", + ["itemize"]={ + ["cs"]="vycet", + ["de"]="aufzaehlung", + ["en"]="itemize", + ["fr"]="détailler", + ["it"]="elenco", + ["nl"]="opsomming", + ["pe"]="آیتم‌بندی", + ["ro"]="enumerare", }, - ["negative"]={ - ["cs"]="negativ", - ["de"]="negativ", - ["en"]="negative", - ["fr"]="negatif", - ["it"]="negativo", - ["nl"]="negatief", - ["pe"]="منفی", - ["ro"]="negativ", + ["its"]={ + ["cs"]="pol", + ["de"]="its", + ["en"]="its", + ["fr"]="els", + ["it"]="its", + ["nl"]="its", + ["pe"]="آیم", + ["ro"]="propriu", }, - ["never"]={ - ["cs"]="nikdy", - ["de"]="nie", - ["en"]="never", - ["fr"]="jamais", - ["it"]="mai", - ["nl"]="nooit", - ["pe"]="هیچگاه", - ["ro"]="niciodata", + ["january"]={ + ["cs"]="leden", + ["de"]="januar", + ["en"]="january", + ["fr"]="janvier", + ["it"]="gennaio", + ["nl"]="januari", + ["pe"]="ژانویه", + ["ro"]="ianuarie", }, - ["new"]={ - ["cs"]="novy", - ["de"]="neu", - ["en"]="new", - ["fr"]="nouveau", - ["it"]="nuovo", - ["nl"]="nieuw", - ["pe"]="جدید", - ["ro"]="nou", + ["joinedup"]={ + ["cs"]="spojeno", + ["de"]="keinabstand", + ["en"]="joinedup", + ["fr"]="sansespaceentre", + ["it"]="unito", + ["nl"]="aansluitend", + ["pe"]="متصل‌بالا", + ["ro"]="unit", }, - ["next"]={ - ["cs"]="dalsi", - ["de"]="folgende", - ["en"]="next", - ["fr"]="prochain", - ["it"]="successivo", - ["nl"]="volgende", - ["pe"]="بعدی", - ["ro"]="urmatorul", + ["july"]={ + ["cs"]="cervenec", + ["de"]="juli", + ["en"]="july", + ["fr"]="juillet", + ["it"]="luglio", + ["nl"]="juli", + ["pe"]="ژولای", + ["ro"]="iulie", }, - ["nextevenpage"]={ - ["cs"]="dalsisudastranka", - ["de"]="naechstegeradeseite", - ["en"]="nextevenpage", - ["fr"]="pagepairesuivante", - ["it"]="paginaparisuccessiva", - ["nl"]="volgendeevenpagina", - ["pe"]="صفحه‌زوج‌بعدی", - ["ro"]="paginaparaurmatoarea", + ["june"]={ + ["cs"]="cerven", + ["de"]="juni", + ["en"]="june", + ["fr"]="juin", + ["it"]="giugno", + ["nl"]="juni", + ["pe"]="ژوئن", + ["ro"]="iunie", }, - ["nextoddpage"]={ - ["cs"]="dalsilichastranka", - ["de"]="naechsteungeradeseite", - ["en"]="nextoddpage", - ["fr"]="pageimpairesuivante", - ["it"]="paginadisparisuccessiva", - ["nl"]="volgendeonevenpagina", - ["pe"]="صفحه‌فردبعدی", - ["ro"]="paginaimparaurmatoarea", + ["keep"]={ + ["cs"]="drzet", + ["de"]="behalte", + ["en"]="keep", + ["fr"]="conserver", + ["it"]="mantieni", + ["nl"]="handhaaf", + ["pe"]="نگهدار", + ["ro"]="mentine", }, - ["nextpage"]={ - ["cs"]="dalsistranka", - ["de"]="folgendeseite", - ["en"]="nextpage", - ["fr"]="pagesuivante", - ["it"]="paginasuccessiva", - ["nl"]="volgendepagina", - ["pe"]="صفحه‌بعدی", - ["ro"]="paginaurmatoare", + ["kerncharacters"]={ + ["en"]="kerncharacters", + ["fr"]="approchercaracteres", }, - ["nextsubpage"]={ - ["cs"]="dalsipodstranka", - ["de"]="folgendeunterseite", - ["en"]="nextsubpage", - ["fr"]="souspagesuivante", - ["it"]="sottopaginasuccessiva", - ["nl"]="volgendesubpagina", - ["pe"]="زیرصفحه‌بعدی", - ["ro"]="urmatoareasubpagina", + ["knockout"]={ + ["cs"]="knockout", + ["de"]="knockout", + ["en"]="knockout", + ["fr"]="knockout", + ["it"]="knockout", + ["nl"]="knockout", + ["pe"]="knockout", + ["ro"]="knockout", }, - ["no"]={ - ["cs"]="ne", - ["de"]="nein", - ["en"]="no", - ["fr"]="non", - ["it"]="no", - ["nl"]="nee", - ["pe"]="نه", - ["ro"]="nu", + ["label"]={ + ["cs"]="popisek", + ["de"]="label", + ["en"]="label", + ["fr"]="etiquette", + ["it"]="etichetta", + ["nl"]="label", + ["pe"]="برچسب", + ["ro"]="eticheta", }, - ["nocheck"]={ - ["cs"]="nocheck", - ["de"]="nocheck", - ["en"]="nocheck", - ["fr"]="nonverifie", - ["it"]="nocheck", - ["nl"]="geencontrole", - ["pe"]="بدون‌بررسی", - ["ro"]="nocheck", + ["landscape"]={ + ["cs"]="nasirku", + ["de"]="querformat", + ["en"]="landscape", + ["fr"]="paysage", + ["it"]="orizzontale", + ["nl"]="liggend", + ["pe"]="صفحه‌گسترده", + ["ro"]="vedere", }, - ["nodepth"]={ - ["en"]="nodepth", + ["last"]={ + ["cs"]="posledni", + ["de"]="letzte", + ["en"]="last", + ["fr"]="dernier", + ["it"]="ultimo", + ["nl"]="laatste", + ["pe"]="آخرین", + ["ro"]="ultim", }, - ["nofit"]={ - ["cs"]="nofit", - ["de"]="nofit", - ["en"]="nofit", - ["fr"]="nofit", - ["it"]="nofit", - ["nl"]="nietpassend", - ["pe"]="بدون‌پرکردن", - ["ro"]="nofit", + ["lastcolumn"]={ + ["cs"]="lastcolumn", + ["de"]="lastcolumn", + ["en"]="lastcolumn", + ["fr"]="dernierecolonne", + ["it"]="lastcolumn", + ["nl"]="laatstekolom", + ["pe"]="آخرین‌ستون", + ["ro"]="lastcolumn", }, - ["nogrid"]={ - ["cs"]="nogrid", - ["de"]="nogrid", - ["en"]="nogrid", - ["fr"]="nogrid", - ["it"]="nogrid", - ["nl"]="geengrid", - ["pe"]="بدون‌توری", - ["ro"]="nogrid", + ["lastpage"]={ + ["cs"]="poslednistrana", + ["de"]="letzteseite", + ["en"]="lastpage", + ["fr"]="dernierepage", + ["it"]="ultimapagina", + ["nl"]="laatstepagina", + ["pe"]="صفحه‌آخر", + ["ro"]="ultimapagina", }, - ["noheight"]={ - ["en"]="noheight", + ["lastpagenumber"]={ + ["cs"]="lastpagenumber", + ["de"]="lastpagenumber", + ["en"]="lastpagenumber", + ["fr"]="numerodenierepage", + ["it"]="lastpagenumber", + ["nl"]="laatstepaginanummer", + ["pe"]="شماه‌صفحه‌آخر", + ["ro"]="lastpagenumber", }, - ["nohz"]={ - ["cs"]="nohz", - ["de"]="nohz", - ["en"]="nohz", - ["fr"]="nohz", - ["it"]="nohz", - ["nl"]="geenhz", - ["pe"]="nohz", - ["ro"]="nohz", + ["lastsubpage"]={ + ["cs"]="poslaednipodstranka", + ["de"]="letzteunterseite", + ["en"]="lastsubpage", + ["fr"]="dernieresouspage", + ["it"]="ultimasottopagina", + ["nl"]="laatstesubpagina", + ["pe"]="زیرصفحه‌آخر", + ["ro"]="ultimasubpagina", }, - ["noline"]={ - ["en"]="noline", + ["layer"]={ + ["cs"]="layer", + ["de"]="layer", + ["en"]="layer", + ["fr"]="calque", + ["it"]="layer", + ["nl"]="layer", + ["pe"]="layer", + ["ro"]="layer", }, - ["nomarking"]={ - ["cs"]="zadneznaceni", - ["de"]="keinebeschriftung", - ["en"]="nomarking", - ["fr"]="sansmarquage", - ["it"]="nomarcature", - ["nl"]="geenmarkering", - ["pe"]="بدون‌نشانه‌گذاری", - ["ro"]="faramarcare", + ["left"]={ + ["cs"]="vlevo", + ["de"]="links", + ["en"]="left", + ["fr"]="gauche", + ["it"]="sinistra", + ["nl"]="links", + ["pe"]="چپ", + ["ro"]="stanga", }, - ["nomenubar"]={ - ["en"]="nomenubar", - ["nl"]="geenmenubalk", + ["leftedge"]={ + ["cs"]="levahrana", + ["de"]="linkekante", + ["en"]="leftedge", + ["fr"]="bordgauche", + ["it"]="bordosinistro", + ["nl"]="linkerrand", + ["pe"]="لبه‌چپ", + ["ro"]="bordurastanga", }, - ["none"]={ - ["cs"]="zadny", - ["de"]="kein", - ["en"]="none", - ["fr"]="rien", - ["it"]="nessuno", - ["nl"]="geen", - ["pe"]="هیچکدام", - ["ro"]="niciunul", + ["lefthanging"]={ + ["cs"]="lefthanging", + ["de"]="lefthanging", + ["en"]="lefthanging", + ["fr"]="suspensiongauche", + ["it"]="lefthanging", + ["nl"]="linkshangend", + ["pe"]="آویزان‌چپ", + ["ro"]="lefthanging", }, - ["nonumber"]={ - ["cs"]="nonumber", - ["de"]="nonumber", - ["en"]="nonumber", - ["fr"]="sansnumero", - ["it"]="nonumber", - ["nl"]="geennummer", - ["pe"]="بدون‌شماره", - ["ro"]="nonumber", + ["leftmargin"]={ + ["cs"]="levyokraj", + ["de"]="linkerrand", + ["en"]="leftmargin", + ["fr"]="margegauche", + ["it"]="marginesinistro", + ["nl"]="linkermarge", + ["pe"]="حاشیه‌چپ", + ["ro"]="marginestanga", }, - ["norepeat"]={ - ["en"]="norepeat", + ["leftpage"]={ + ["cs"]="levastranka", + ["de"]="linkerseite", + ["en"]="leftpage", + ["fr"]="surpagegauche", + ["it"]="paginasinistra", + ["nl"]="linkerpagina", + ["pe"]="صفحه‌چپ", + ["ro"]="paginastanga", }, - ["normal"]={ - ["cs"]="normalni", - ["de"]="normal", - ["en"]="normal", - ["fr"]="normal", - ["it"]="normale", - ["nl"]="normaal", - ["pe"]="نرمال", - ["ro"]="normal", + ["lefttoright"]={ + ["cs"]="lefttoright", + ["de"]="lefttoright", + ["en"]="lefttoright", + ["fr"]="gaucheadroite", + ["it"]="lefttoright", + ["nl"]="lefttoright", + ["pe"]="lefttoright", + ["ro"]="lefttoright", }, - ["nospacing"]={ - ["cs"]="nospacing", - ["de"]="nospacing", - ["en"]="nospacing", - ["fr"]="sansespacement", - ["it"]="nospacing", - ["nl"]="geenspatiering", - ["pe"]="بدون‌فضاگذاری", - ["ro"]="nospacing", + ["legend"]={ + ["cs"]="legenda", + ["de"]="legende", + ["en"]="legend", + ["fr"]="legende", + ["it"]="legenda", + ["nl"]="legenda", + ["pe"]="راهنما", + ["ro"]="legenda", }, - ["not"]={ - ["cs"]="ne", - ["de"]="nicht", - ["en"]="not", - ["fr"]="pas", - ["it"]="non", - ["nl"]="niet", - ["pe"]="بدون", - ["ro"]="nu", + ["less"]={ + ["en"]="less", + ["fr"]="moins", + ["nl"]="minder", }, - ["notation"]={ - ["en"]="notation", + ["lesshyphenation"]={ + ["cs"]="lesshyphenation", + ["de"]="lesshyphenation", + ["en"]="lesshyphenation", + ["fr"]="moinsdecesure", + ["it"]="lesshyphenation", + ["nl"]="lesshyphenation", + ["pe"]="شکست‌کلمات‌کمتر", + ["ro"]="lesshyphenation", }, - ["note"]={ - ["en"]="note", + ["letterspacing"]={ + ["en"]="letterspacing", + ["fr"]="espacementlettre", }, - ["nothanging"]={ - ["cs"]="nothanging", - ["de"]="nothanging", - ["en"]="nothanging", - ["fr"]="nonsuspendu", - ["it"]="nonsospeso", - ["nl"]="niethangend", - ["pe"]="بدون‌آویزان‌کردن", - ["ro"]="nothanging", + ["line"]={ + ["cs"]="radek", + ["de"]="zeile", + ["en"]="line", + ["fr"]="ligne", + ["it"]="riga", + ["nl"]="regel", + ["pe"]="خط", + ["ro"]="linie", }, - ["nothyphenated"]={ - ["cs"]="nothyphenated", - ["de"]="nothyphenated", - ["en"]="nothyphenated", - ["fr"]="nothyphenated", - ["it"]="nonsillabato", - ["nl"]="nietafgebroken", - ["pe"]="بدون‌شکست", - ["ro"]="nedespsilabe", + ["linenote"]={ + ["cs"]="linenote", + ["de"]="linenote", + ["en"]="linenote", + ["fr"]="noteligne", + ["it"]="linenote", + ["nl"]="regelnoot", + ["pe"]="خط‌نوشت", + ["ro"]="linenote", }, - ["november"]={ - ["cs"]="listopad", - ["de"]="november", - ["en"]="november", - ["fr"]="novembre", - ["it"]="novembre", - ["nl"]="november", - ["pe"]="نوامبر", - ["ro"]="noiembrie", + ["lines"]={ + ["cs"]="radky", + ["de"]="zeilen", + ["en"]="lines", + ["fr"]="lignes", + ["it"]="righe", + ["nl"]="regels", + ["pe"]="خطها", + ["ro"]="linii", }, - ["nowhere"]={ - ["cs"]="nikde", - ["de"]="nirgens", - ["en"]="nowhere", - ["fr"]="nulpart", - ["it"]="danessunaparte", - ["nl"]="nergens", - ["pe"]="هیچ‌حا", - ["ro"]="niciunde", + ["linked"]={ + ["en"]="linked", + ["fr"]="lie", }, - ["nowhite"]={ - ["cs"]="zadnabila", - ["de"]="keinweiss", - ["en"]="nowhite", - ["fr"]="sansblanc", - ["it"]="nobianco", - ["nl"]="geenwit", - ["pe"]="سفید‌نه", - ["ro"]="faraalb", + ["list"]={ + ["cs"]="seznam", + ["de"]="liste", + ["en"]="list", + ["fr"]="liste", + ["it"]="elenco", + ["nl"]="lijst", + ["pe"]="لیست", + ["ro"]="lista", }, - ["number"]={ - ["cs"]="cislo", - ["de"]="nummer", - ["en"]="number", - ["fr"]="numero", - ["it"]="numero", - ["nl"]="nummer", - ["pe"]="شماره", - ["ro"]="numar", + ["local"]={ + ["cs"]="lokalne", + ["de"]="lokal", + ["en"]="local", + ["fr"]="local", + ["it"]="locale", + ["nl"]="lokaal", + ["pe"]="موضعی", + ["ro"]="local", }, - ["numbers"]={ - ["cs"]="cisla", - ["de"]="ziffern", - ["en"]="numbers", - ["fr"]="numeros", - ["it"]="numeri", - ["nl"]="cijfers", - ["pe"]="شماره‌ها", - ["ro"]="numere", + ["localenvironment"]={ + ["cs"]="lokalnihoprostredi", + ["de"]="lokaleumgebung", + ["en"]="localenvironment", + ["fr"]="environnementlocal", + ["it"]="ambientelocale", + ["nl"]="deelomgeving", + ["pe"]="محیط‌موضعی", + ["ro"]="mediulocal", }, - ["october"]={ - ["cs"]="rijen", - ["de"]="oktober", - ["en"]="october", - ["fr"]="octobre", - ["it"]="ottobre", - ["nl"]="oktober", - ["pe"]="اکتبر", - ["ro"]="octombrie", + ["logo"]={ + ["cs"]="logo", + ["de"]="logo", + ["en"]="logo", + ["fr"]="logo", + ["it"]="logo", + ["nl"]="logo", + ["pe"]="آرم", + ["ro"]="logo", }, - ["odd"]={ - ["cs"]="liche", - ["de"]="ungerade", - ["en"]="odd", - ["fr"]="impair", - ["it"]="dispari", - ["nl"]="oneven", - ["pe"]="فرد", - ["ro"]="impar", + ["logos"]={ + ["cs"]="loga", + ["de"]="logos", + ["en"]="logos", + ["fr"]="logos", + ["it"]="loghi", + ["nl"]="logos", + ["pe"]="آرمها", + ["ro"]="logos", }, - ["off"]={ - ["cs"]="vyp", - ["de"]="aus", - ["en"]="off", - ["fr"]="desactive", - ["it"]="disattivo", - ["nl"]="uit", - ["pe"]="خاموش", - ["ro"]="dezactivat", + ["lohi"]={ + ["cs"]="nivy", + ["de"]="hoti", + ["en"]="lohi", + ["fr"]="inex", + ["it"]="pedap", + ["nl"]="laho", + ["pe"]="پابا", + ["ro"]="lohi", }, - ["offset"]={ - ["cs"]="offset", - ["de"]="offset", - ["en"]="offset", - ["fr"]="offset", - ["it"]="offset", - ["nl"]="offset", - ["pe"]="آفست", - ["ro"]="offset", + ["long"]={ + ["en"]="long", + ["fr"]="long", }, - ["old"]={ - ["cs"]="old", - ["de"]="old", - ["en"]="old", - ["fr"]="old", - ["it"]="old", - ["nl"]="oud", - ["pe"]="قدیمی", - ["ro"]="old", + ["loose"]={ + ["cs"]="uvolnene", + ["de"]="lose", + ["en"]="loose", + ["fr"]="envrac", + ["it"]="lento", + ["nl"]="los", + ["pe"]="شل", + ["ro"]="larg", }, - ["oldstyle"]={ - ["en"]="oldstyle", + ["low"]={ + ["cs"]="nizko", + ["de"]="tief", + ["en"]="low", + ["fr"]="ind", + ["it"]="basso", + ["nl"]="laag", + ["pe"]="پایین", + ["ro"]="jos", }, - ["fractions"]={ - ["en"]="fractions", + ["ls"]={ + ["cs"]="ls", + ["de"]="ls", + ["en"]="ls", + ["fr"]="ls", + ["it"]="ls", + ["nl"]="ls", + ["pe"]="ls", + ["ro"]="ls", }, - ["on"]={ - ["cs"]="zap", - ["de"]="an", - ["en"]="on", - ["fr"]="actif", - ["it"]="attivo", - ["nl"]="aan", - ["pe"]="روی", - ["ro"]="on", + ["makeup"]={ + ["cs"]="zlom", + ["de"]="umbruch", + ["en"]="makeup", + ["fr"]="composition", + ["it"]="makeup", + ["nl"]="opmaak", + ["pe"]="آرایش", + ["ro"]="marcaj", }, - ["one"]={ - ["cs"]="jedna", - ["de"]="eins", - ["en"]="one", - ["fr"]="un", - ["it"]="uno", - ["nl"]="een", - ["pe"]="یک", - ["ro"]="unu", + ["mar"]={ + ["cs"]="mar", + ["de"]="mar", + ["en"]="mar", + ["fr"]="rem", + ["it"]="mar", + ["nl"]="mar", + ["pe"]="حاش", + ["ro"]="mar", }, - ["opposite"]={ - ["cs"]="naproti", - ["de"]="gegenueber", - ["en"]="opposite", - ["fr"]="opposition", - ["it"]="opposto", - ["nl"]="naast", - ["pe"]="مخالف", - ["ro"]="opus", + ["march"]={ + ["cs"]="brezen", + ["de"]="maerz", + ["en"]="march", + ["fr"]="mars", + ["it"]="marzo", + ["nl"]="maart", + ["pe"]="مارس", + ["ro"]="martie", }, - ["outer"]={ - ["cs"]="vnejsi", - ["de"]="aussen", - ["en"]="outer", - ["fr"]="exterieur", - ["it"]="esterno", - ["nl"]="buiten", - ["pe"]="خارجی", - ["ro"]="extern", + ["margin"]={ + ["cs"]="marginalie", + ["de"]="marginalie", + ["en"]="margin", + ["fr"]="marge", + ["it"]="margine", + ["nl"]="marge", + ["pe"]="حاشیه", + ["ro"]="margine", }, - ["outeredge"]={ - ["cs"]="outeredge", - ["de"]="outeredge", - ["en"]="outeredge", - ["fr"]="bordexterieur", - ["it"]="bordoesterno", - ["nl"]="buitenrand", - ["pe"]="لبه‌خارجی", - ["ro"]="outeredge", + ["marginedge"]={ + ["cs"]="textovahrana", + ["de"]="marginalkante", + ["en"]="marginedge", + ["fr"]="margebord", + ["it"]="bordomargine", + ["nl"]="kantlijn", + ["pe"]="لبه‌حاشیه", + ["ro"]="marginebordura", }, - ["outermargin"]={ - ["cs"]="outermargin", - ["de"]="outermargin", - ["en"]="outermargin", - ["fr"]="margeexterieure", - ["it"]="margineesterno", - ["nl"]="buitenmarge", - ["pe"]="حاشیه‌خارجی", - ["ro"]="outermargin", + ["margintext"]={ + ["cs"]="marginalnitext", + ["de"]="marginaltext", + ["en"]="margintext", + ["fr"]="textemarge", + ["it"]="testoinmargine", + ["nl"]="margetekst", + ["pe"]="متن‌حاشیه", + ["ro"]="textmarginal", }, - ["overbar"]={ - ["cs"]="nadtrzeno", - ["de"]="ueberstrichen", - ["en"]="overbar", - ["fr"]="overbar", - ["it"]="sopralinea", - ["nl"]="overstreep", - ["pe"]="میله‌رو", - ["ro"]="barasus", + ["margintitle"]={ + ["cs"]="titulmarginalie", + ["de"]="marginaltitel", + ["en"]="margintitle", + ["fr"]="titremarge", + ["it"]="titoloinmargine", + ["nl"]="margetitel", + ["pe"]="عنوان‌حاشیه", + ["ro"]="titlumarginal", }, - ["overbars"]={ - ["cs"]="nadtrzeni", - ["de"]="ueberstreichen", - ["en"]="overbars", - ["fr"]="overbars", - ["it"]="sopralinee", - ["nl"]="overstrepen", - ["pe"]="میله‌ها‌رو", - ["ro"]="supralinie", + ["marking"]={ + ["cs"]="znaceni", + ["de"]="beschriftung", + ["en"]="marking", + ["fr"]="marquage", + ["it"]="marcatura", + ["nl"]="markering", + ["pe"]="نشانه‌گذاری", + ["ro"]="marcaje", }, - ["overlay"]={ - ["cs"]="prekryv", - ["de"]="overlay", - ["en"]="overlay", - ["fr"]="revetement", - ["it"]="sovrapponi", - ["nl"]="overlay", - ["pe"]="پوشش", - ["ro"]="overlay", + ["math"]={ + ["en"]="math", + ["fr"]="math", }, - ["overprint"]={ - ["cs"]="overprint", - ["de"]="overprint", - ["en"]="overprint", - ["fr"]="overprint", - ["it"]="overprint", - ["nl"]="overprint", - ["pe"]="overprint", - ["ro"]="overprint", + ["mathalignment"]={ + ["cs"]="mathalignment", + ["de"]="mathalignment", + ["en"]="mathalignment", + ["fr"]="alignementmath", + ["it"]="mathalignment", + ["nl"]="wiskundeuitlijnen", + ["pe"]="تنظیم‌ریاضی", + ["ro"]="mathalignment", }, - ["overstrike"]={ - ["cs"]="preskrtnuto", - ["de"]="durchgestrichen", - ["en"]="overstrike", - ["fr"]="surlignetout", - ["it"]="sbarrato", - ["nl"]="doorstreep", - ["pe"]="خط‌زدن", - ["ro"]="liniepeste", + ["mathcases"]={ + ["cs"]="mathcases", + ["de"]="mathcases", + ["en"]="mathcases", + ["fr"]="casmath", + ["it"]="mathcases", + ["nl"]="mathcases", + ["pe"]="حالتهای‌ریاضی", + ["ro"]="mathcases", }, - ["overstrikes"]={ - ["cs"]="preskrtnuti", - ["de"]="durchstreichen", - ["en"]="overstrikes", - ["fr"]="surligne", - ["it"]="sbarrati", - ["nl"]="doorstrepen", - ["pe"]="خط‌زدنها", - ["ro"]="liniipeste", + ["mathematics"]={ + ["cs"]="mathematika", + ["de"]="mathematik", + ["en"]="mathematics", + ["fr"]="mathematics", + ["it"]="matematica", + ["nl"]="wiskunde", + ["pe"]="ریاضی", + ["ro"]="matematica", }, - ["packed"]={ - ["cs"]="zhustene", - ["de"]="gepackt", - ["en"]="packed", - ["fr"]="groupe", - ["it"]="impaccato", - ["nl"]="opelkaar", - ["pe"]="فشرده", - ["ro"]="impachetat", + ["mathmatrix"]={ + ["cs"]="mathmatrix", + ["de"]="mathmatrix", + ["en"]="mathmatrix", + ["fr"]="matricemath", + ["it"]="mathmatrix", + ["nl"]="wiskundematrix", + ["pe"]="ماتریش‌ریاضی", + ["ro"]="mathmatrix", }, - ["page"]={ - ["cs"]="stranka", - ["de"]="seite", - ["en"]="page", - ["fr"]="page", - ["it"]="pagina", - ["nl"]="pagina", - ["pe"]="صفحه", - ["ro"]="pagina", + ["max"]={ + ["cs"]="max", + ["de"]="max", + ["en"]="max", + ["fr"]="max", + ["it"]="max", + ["nl"]="max", + ["pe"]="بیشترین", + ["ro"]="max", }, - ["pagecomment"]={ - ["cs"]="komentarstranky", - ["de"]="pagecomment", - ["en"]="pagecomment", - ["fr"]="commentairepage", - ["it"]="commentopagina", - ["nl"]="paginacommentaar", - ["pe"]="توضیح‌صفحه", - ["ro"]="comentariupagina", + ["maxdepth"]={ + ["en"]="maxdepth", + ["fr"]="profondeurmax", + ["nl"]="maxdiepte", }, - ["pagenumber"]={ - ["cs"]="cislostranky", - ["de"]="seitennummer", - ["en"]="pagenumber", - ["fr"]="numeropage", - ["it"]="numeropagina", - ["nl"]="paginanummer", - ["pe"]="شماره‌صفحه", - ["ro"]="numarpagina", + ["maxheight"]={ + ["en"]="maxheight", + ["fr"]="hauteurmax", + ["nl"]="maxhoogte", }, - ["paper"]={ - ["cs"]="papir", - ["de"]="papier", - ["en"]="paper", - ["fr"]="papier", - ["it"]="carta", - ["nl"]="papier", - ["pe"]="برگ", - ["ro"]="foaie", + ["maxwidth"]={ + ["en"]="maxwidth", + ["fr"]="largeurmax", + ["nl"]="maxbreedte", }, - ["paragraph"]={ - ["cs"]="odstavec", - ["de"]="absatz", - ["en"]="paragraph", - ["fr"]="paragraphe", - ["it"]="capoverso", - ["nl"]="alinea", - ["pe"]="پاراگراف", - ["ro"]="paragraf", + ["may"]={ + ["cs"]="kveten", + ["de"]="mai", + ["en"]="may", + ["fr"]="mai", + ["it"]="maggio", + ["nl"]="mei", + ["pe"]="مه", + ["ro"]="mai", }, - ["part"]={ - ["cs"]="cast", - ["de"]="teil", - ["en"]="part", - ["fr"]="partie", - ["it"]="parte", - ["nl"]="deel", - ["pe"]="قسمت", - ["ro"]="parte", + ["mediaeval"]={ + ["cs"]="stredoveky", + ["de"]="mittelalterlich", + ["en"]="mediaeval", + ["fr"]="medieval", + ["it"]="medievale", + ["nl"]="mediaeval", + ["pe"]="mediaeval", + ["ro"]="medieval", }, - ["positive"]={ - ["cs"]="positiv", - ["de"]="positiv", - ["en"]="positive", - ["fr"]="positif", - ["it"]="positivo", - ["nl"]="positief", - ["pe"]="مثبت", - ["ro"]="positiv", + ["medium"]={ + ["cs"]="stredni", + ["de"]="mittel", + ["en"]="medium", + ["fr"]="moyen", + ["it"]="medio", + ["nl"]="middel", + ["pe"]="متوسط", + ["ro"]="mediu", }, - ["postponing"]={ - ["cs"]="odlozit", - ["de"]="verschieben", - ["en"]="postponing", - ["fr"]="postponing", - ["it"]="posporre", - ["nl"]="uitstellen", - ["pe"]="تاخیر", - ["ro"]="postponing", + ["middle"]={ + ["cs"]="nastred", + ["de"]="mittig", + ["en"]="middle", + ["fr"]="milieu", + ["it"]="centro", + ["nl"]="midden", + ["pe"]="میان", + ["ro"]="centru", }, - ["postscript"]={ - ["cs"]="postscript", - ["de"]="postscript", - ["en"]="postscript", - ["fr"]="postscript", - ["it"]="postscript", - ["nl"]="postscript", - ["pe"]="پست‌اسکریپت", - ["ro"]="postscript", + ["min"]={ + ["cs"]="min", + ["de"]="min", + ["en"]="min", + ["fr"]="min", + ["it"]="min", + ["nl"]="min", + ["pe"]="کمترین", + ["ro"]="min", }, - ["precedingpage"]={ - ["en"]="precedingpage", - ["nl"]="voorafgaandepagina", + ["mindepth"]={ + ["en"]="mindepth", + ["fr"]="profondeurmin", + ["nl"]="mindiepte", }, - ["preference"]={ - ["cs"]="nastaveni", - ["de"]="einstellung", - ["en"]="preference", - ["fr"]="preference", - ["it"]="preferenza", - ["nl"]="voorkeur", - ["pe"]="ترجیح", - ["ro"]="preferinta", + ["minheight"]={ + ["cs"]="minvyska", + ["de"]="minhoehe", + ["en"]="minheight", + ["fr"]="hauteurmin", + ["it"]="altezzamin", + ["nl"]="minhoogte", + ["pe"]="کمترین‌ارتفاع", + ["ro"]="inaltimeminima", }, - ["preview"]={ - ["cs"]="nahled", - ["de"]="vorschau", - ["en"]="preview", - ["fr"]="previsualisation", - ["it"]="anteprima", - ["nl"]="preview", - ["pe"]="پیش‌دید", - ["ro"]="previzualizare", + ["minwidth"]={ + ["cs"]="minsirka", + ["de"]="minbreite", + ["en"]="minwidth", + ["fr"]="largeurmin", + ["it"]="ampiezzamin", + ["nl"]="minbreedte", + ["pe"]="کمترین‌عرض", + ["ro"]="latimeminima", }, - ["previous"]={ - ["cs"]="predchozi", - ["de"]="vorig", - ["en"]="previous", - ["fr"]="precedent", - ["it"]="precedente", - ["nl"]="vorige", - ["pe"]="قبلی", - ["ro"]="precedent", + ["mirrored"]={ + ["cs"]="zrcadleno", + ["de"]="gespiegelt", + ["en"]="mirrored", + ["fr"]="reflete", + ["it"]="riflesso", + ["nl"]="gespiegeld", + ["pe"]="منعکس", + ["ro"]="oglindit", }, - ["previousevenpage"]={ - ["cs"]="predchozisudastranka", - ["de"]="vorigegeradeseite", - ["en"]="previousevenpage", - ["fr"]="pagepaireprecedente", - ["it"]="paginapariprecedente", - ["nl"]="vorigeevenpagina", - ["pe"]="صفحه‌زوج‌قبلی", - ["ro"]="paginaparaprecedenta", + ["mixed"]={ + ["en"]="mixed", + ["fr"]="mixte", }, - ["previousoddpage"]={ - ["cs"]="predchozilichastranka", - ["de"]="vorigeungeradeseite", - ["en"]="previousoddpage", - ["fr"]="pageimpaireprecedente", - ["it"]="paginadispariprecedente", - ["nl"]="vorigeonevenpagina", - ["pe"]="صفحه‌فردقبلی", - ["ro"]="paginaimparaprecedenta", + ["monday"]={ + ["cs"]="pondeli", + ["de"]="montag", + ["en"]="monday", + ["fr"]="lundi", + ["it"]="lunedi", + ["nl"]="maandag", + ["pe"]="دوشنبه", + ["ro"]="luni", }, - ["previouspage"]={ - ["cs"]="predchozistranka", - ["de"]="vorigeseite", - ["en"]="previouspage", - ["fr"]="pageprecedente", - ["it"]="paginaprecedente", - ["nl"]="vorigepagina", - ["pe"]="صفحه‌قبلی", - ["ro"]="paginaanterioara", + ["mono"]={ + ["cs"]="mono", + ["de"]="mono", + ["en"]="mono", + ["fr"]="mono", + ["it"]="mono", + ["nl"]="mono", + ["pe"]="مونو", + ["ro"]="mono", }, - ["previoussubpage"]={ - ["cs"]="predchozipodstranka", - ["de"]="vorigeunterseite", - ["en"]="previoussubpage", - ["fr"]="souspageprecedente", - ["it"]="sottopaginaprecedente", - ["nl"]="vorigesubpagina", - ["pe"]="زیرصفحه‌قبلی", - ["ro"]="subpaginaanterioara", + ["monobold"]={ + ["cs"]="monotucne", + ["de"]="monofett", + ["en"]="monobold", + ["fr"]="monogras", + ["it"]="monograssetto", + ["nl"]="monovet", + ["pe"]="monobold", + ["ro"]="monoaldin", }, - ["print"]={ - ["en"]="print", - ["nl"]="print", + ["mononormal"]={ + ["en"]="mononormal", + ["fr"]="normalmono", }, - ["printable"]={ - ["cs"]="tisknutelne", - ["de"]="druckbar", - ["en"]="printable", - ["fr"]="editable", - ["it"]="stampabile", - ["nl"]="printbaar", - ["pe"]="قابل‌چاپ", - ["ro"]="tiparibil", + ["month"]={ + ["cs"]="mesic", + ["de"]="monat", + ["en"]="month", + ["fr"]="mois", + ["it"]="mese", + ["nl"]="maand", + ["pe"]="ماه", + ["ro"]="luna", }, - ["process"]={ - ["cs"]="process", - ["de"]="process", - ["en"]="process", - ["fr"]="process", - ["it"]="process", - ["nl"]="proces", - ["pe"]="پردازش", - ["ro"]="process", + ["more"]={ + ["en"]="more", + ["fr"]="plus", + ["nl"]="meer", }, - ["product"]={ - ["cs"]="produkt", - ["de"]="produkt", - ["en"]="product", - ["fr"]="produit", - ["it"]="prodotto", - ["nl"]="produkt", - ["pe"]="محصول", - ["ro"]="produs", + ["morehyphenation"]={ + ["cs"]="morehyphenation", + ["de"]="morehyphenation", + ["en"]="morehyphenation", + ["fr"]="plusdecesure", + ["it"]="morehyphenation", + ["nl"]="morehyphenation", + ["pe"]="شکست‌کلمات‌بیشتر", + ["ro"]="morehyphenation", + }, + ["name"]={ + ["cs"]="jmeno", + ["de"]="name", + ["en"]="name", + ["fr"]="nom", + ["it"]="nome", + ["nl"]="naam", + ["pe"]="نام", + ["ro"]="nume", }, - ["program"]={ - ["cs"]="program", - ["de"]="programm", - ["en"]="program", - ["fr"]="programme", - ["it"]="programma", - ["nl"]="programma", - ["pe"]="برنامه", - ["ro"]="program", + ["narrow"]={ + ["cs"]="uzky", + ["de"]="schmall", + ["en"]="narrow", + ["fr"]="etroit", + ["it"]="stretto", + ["nl"]="smal", + ["pe"]="نازک", + ["ro"]="ingust", }, - ["project"]={ - ["cs"]="projekt", - ["de"]="projekt", - ["en"]="project", - ["fr"]="projet", - ["it"]="progetto", - ["nl"]="project", - ["pe"]="پروژه", - ["ro"]="proiect", + ["negative"]={ + ["cs"]="negativ", + ["de"]="negativ", + ["en"]="negative", + ["fr"]="negatif", + ["it"]="negativo", + ["nl"]="negatief", + ["pe"]="منفی", + ["ro"]="negativ", }, - ["protected"]={ - ["cs"]="chranene", - ["de"]="geschuetzt", - ["en"]="protected", - ["fr"]="protege", - ["it"]="protetto", - ["nl"]="beschermd", - ["pe"]="حفاظت‌شده", - ["ro"]="protejat", + ["never"]={ + ["cs"]="nikdy", + ["de"]="nie", + ["en"]="never", + ["fr"]="jamais", + ["it"]="mai", + ["nl"]="nooit", + ["pe"]="هیچگاه", + ["ro"]="niciodata", }, - ["quadruple"]={ - ["cs"]="ctyrnasobny", - ["de"]="viertel", - ["en"]="quadruple", - ["fr"]="quadruple", - ["it"]="quadruplo", - ["nl"]="viertal", - ["pe"]="quadruple", - ["ro"]="cvadrupul", + ["new"]={ + ["cs"]="novy", + ["de"]="neu", + ["en"]="new", + ["fr"]="nouveau", + ["it"]="nuovo", + ["nl"]="nieuw", + ["pe"]="جدید", + ["ro"]="nou", }, - ["quarterline"]={ - ["en"]="quarterline", - ["nl"]="kwartregel", + ["next"]={ + ["cs"]="dalsi", + ["de"]="folgende", + ["en"]="next", + ["fr"]="suivant", + ["it"]="successivo", + ["nl"]="volgende", + ["pe"]="بعدی", + ["ro"]="urmatorul", }, - ["quotation"]={ - ["cs"]="citace", - ["de"]="zitat", - ["en"]="quotation", - ["fr"]="citation", - ["it"]="citazione", - ["nl"]="citaat", - ["pe"]="نقل‌قول", - ["ro"]="citat", + ["nextevenpage"]={ + ["cs"]="dalsisudastranka", + ["de"]="naechstegeradeseite", + ["en"]="nextevenpage", + ["fr"]="pagepairesuivante", + ["it"]="paginaparisuccessiva", + ["nl"]="volgendeevenpagina", + ["pe"]="صفحه‌زوج‌بعدی", + ["ro"]="paginaparaurmatoarea", }, - ["quote"]={ - ["cs"]="citovat", - ["de"]="zitieren", - ["en"]="quote", - ["fr"]="citer", - ["it"]="menzione", - ["nl"]="citeer", - ["pe"]="نقل", - ["ro"]="minicitat", + ["nextoddpage"]={ + ["cs"]="dalsilichastranka", + ["de"]="naechsteungeradeseite", + ["en"]="nextoddpage", + ["fr"]="pageimpairesuivante", + ["it"]="paginadisparisuccessiva", + ["nl"]="volgendeonevenpagina", + ["pe"]="صفحه‌فردبعدی", + ["ro"]="paginaimparaurmatoarea", }, - ["ran"]={ - ["cs"]="rozsah", - ["de"]="ran", - ["en"]="ran", - ["fr"]="cours", - ["it"]="corse", - ["nl"]="ran", - ["pe"]="برد", - ["ro"]="rulat", + ["nextpage"]={ + ["cs"]="dalsistranka", + ["de"]="folgendeseite", + ["en"]="nextpage", + ["fr"]="pagesuivante", + ["it"]="paginasuccessiva", + ["nl"]="volgendepagina", + ["pe"]="صفحه‌بعدی", + ["ro"]="paginaurmatoare", }, - ["random"]={ - ["cs"]="nahodny", - ["de"]="zufaellig", - ["en"]="random", - ["fr"]="aleatoire", - ["it"]="casuale", - ["nl"]="willekeurig", - ["pe"]="تصادفی", - ["ro"]="aleator", + ["nextsubpage"]={ + ["cs"]="dalsipodstranka", + ["de"]="folgendeunterseite", + ["en"]="nextsubpage", + ["fr"]="souspagesuivante", + ["it"]="sottopaginasuccessiva", + ["nl"]="volgendesubpagina", + ["pe"]="زیرصفحه‌بعدی", + ["ro"]="urmatoareasubpagina", }, - ["readonly"]={ - ["cs"]="pouzeprocteni", - ["de"]="nurlesbar", - ["en"]="readonly", - ["fr"]="lectureseule", - ["it"]="solalettura", - ["nl"]="alleenleesbaar", - ["pe"]="تنهاخواندنی", - ["ro"]="readonly", + ["nine"]={ + ["cs"]="nine", + ["de"]="neun", + ["en"]="nine", + ["fr"]="neuf", + ["it"]="nine", + ["nl"]="negen", + ["pe"]="nine", + ["ro"]="nine", }, - ["rectangular"]={ - ["cs"]="pravouhly", - ["de"]="rechteckig", - ["en"]="rectangular", - ["fr"]="rectangulaire", - ["it"]="rettangolare", - ["nl"]="recht", - ["pe"]="چهارگوشه", - ["ro"]="rectangular", + ["no"]={ + ["cs"]="ne", + ["de"]="nein", + ["en"]="no", + ["fr"]="non", + ["it"]="no", + ["nl"]="nee", + ["pe"]="نه", + ["ro"]="nu", }, - ["reference"]={ - ["cs"]="odkaz", - ["de"]="referenz", - ["en"]="reference", - ["fr"]="reference", - ["it"]="riferimento", - ["nl"]="referentie", - ["pe"]="مرجع", - ["ro"]="referinta", + ["nocheck"]={ + ["cs"]="nocheck", + ["de"]="nocheck", + ["en"]="nocheck", + ["fr"]="sansverifier", + ["it"]="nocheck", + ["nl"]="geencontrole", + ["pe"]="بدون‌بررسی", + ["ro"]="nocheck", }, - ["referral"]={ - ["cs"]="znacka", - ["de"]="merkmal", - ["en"]="referral", - ["fr"]="referral", - ["it"]="referral", - ["nl"]="kenmerk", - ["pe"]="مراجعه", - ["ro"]="referinta", + ["nodepth"]={ + ["en"]="nodepth", + ["fr"]="sansprodondeur", }, - ["register"]={ - ["cs"]="rejstrik", - ["de"]="register", - ["en"]="register", - ["fr"]="registre", - ["it"]="registro", - ["nl"]="register", - ["pe"]="ثبت", - ["ro"]="registru", + ["nofit"]={ + ["cs"]="nofit", + ["de"]="nofit", + ["en"]="nofit", + ["fr"]="sansadapter", + ["it"]="nofit", + ["nl"]="nietpassend", + ["pe"]="بدون‌پرکردن", + ["ro"]="nofit", }, - ["regular"]={ - ["cs"]="pravidelne", - ["de"]="regular", - ["en"]="regular", - ["fr"]="regulier", - ["it"]="regolare", - ["nl"]="regular", - ["pe"]="منظم", - ["ro"]="regular", + ["nogrid"]={ + ["cs"]="nogrid", + ["de"]="nogrid", + ["en"]="nogrid", + ["fr"]="sansgrille", + ["it"]="nogrid", + ["nl"]="geengrid", + ["pe"]="بدون‌توری", + ["ro"]="nogrid", + }, + ["noheight"]={ + ["en"]="noheight", + ["fr"]="sanshauteur", }, - ["relative"]={ - ["cs"]="relativni", - ["de"]="relativ", - ["en"]="relative", - ["fr"]="relatif", - ["it"]="relativo", - ["nl"]="relatief", - ["pe"]="نسبی", - ["ro"]="relativ", + ["nohz"]={ + ["cs"]="nohz", + ["de"]="nohz", + ["en"]="nohz", + ["fr"]="sanshz", + ["it"]="nohz", + ["nl"]="geenhz", + ["pe"]="nohz", + ["ro"]="nohz", }, - ["repeat"]={ - ["cs"]="opakovat", - ["de"]="wiederholen", - ["en"]="repeat", - ["fr"]="repete", - ["it"]="ripeti", - ["nl"]="herhaal", - ["pe"]="تکرار", - ["ro"]="repetat", + ["noline"]={ + ["en"]="noline", + ["fr"]="sansligne", }, - ["required"]={ - ["cs"]="pozadovane", - ["de"]="obligatorisch", - ["en"]="required", - ["fr"]="recquis", - ["it"]="richiestp", - ["nl"]="verplicht", - ["pe"]="موردنیاز", - ["ro"]="obligatoriu", + ["nomarking"]={ + ["cs"]="zadneznaceni", + ["de"]="keinebeschriftung", + ["en"]="nomarking", + ["fr"]="sansmarquage", + ["it"]="nomarcature", + ["nl"]="geenmarkering", + ["pe"]="بدون‌نشانه‌گذاری", + ["ro"]="faramarcare", }, - ["reset"]={ - ["cs"]="reset", - ["de"]="zuruecksetzten", - ["en"]="reset", - ["fr"]="raz", - ["it"]="reimposta", - ["nl"]="reset", - ["pe"]="بازنشانی", - ["ro"]="reset", + ["nomenubar"]={ + ["en"]="nomenubar", + ["fr"]="sansbarremenu", + ["nl"]="geenmenubalk", }, - ["reverse"]={ - ["cs"]="reverse", - ["de"]="reverse", - ["en"]="reverse", - ["fr"]="inverse", - ["it"]="invertito", - ["nl"]="omgekeerd", - ["pe"]="برعکس", - ["ro"]="reverse", + ["none"]={ + ["cs"]="zadny", + ["de"]="kein", + ["en"]="none", + ["fr"]="aucun", + ["it"]="nessuno", + ["nl"]="geen", + ["pe"]="هیچکدام", + ["ro"]="niciunul", }, - ["right"]={ - ["cs"]="vpravo", - ["de"]="rechts", - ["en"]="right", - ["fr"]="droite", - ["it"]="destra", - ["nl"]="rechts", - ["pe"]="راست", - ["ro"]="dreapta", + ["nonumber"]={ + ["cs"]="nonumber", + ["de"]="nonumber", + ["en"]="nonumber", + ["fr"]="sansnumero", + ["it"]="nonumber", + ["nl"]="geennummer", + ["pe"]="بدون‌شماره", + ["ro"]="nonumber", }, - ["rightedge"]={ - ["cs"]="pravahrana", - ["de"]="rechterkante", - ["en"]="rightedge", - ["fr"]="borddroit", - ["it"]="bordodestro", - ["nl"]="rechterrand", - ["pe"]="لبه‌راست", - ["ro"]="borduradreapta", + ["norepeat"]={ + ["en"]="norepeat", + ["fr"]="sansrepetition", }, - ["righthanging"]={ - ["cs"]="righthanging", - ["de"]="righthanging", - ["en"]="righthanging", - ["fr"]="righthanging", - ["it"]="righthanging", - ["nl"]="rechtshangend", - ["pe"]="آویزان‌کردن‌راست", - ["ro"]="righthanging", + ["normal"]={ + ["cs"]="normalni", + ["de"]="normal", + ["en"]="normal", + ["fr"]="normal", + ["it"]="normale", + ["nl"]="normaal", + ["pe"]="نرمال", + ["ro"]="normal", }, - ["rightmargin"]={ - ["cs"]="pravyokraj", - ["de"]="rechterrand", - ["en"]="rightmargin", - ["fr"]="margedroite", - ["it"]="marginedestro", - ["nl"]="rechtermarge", - ["pe"]="حاشیه‌راست", - ["ro"]="marginedreapta", + ["nospacing"]={ + ["cs"]="nospacing", + ["de"]="nospacing", + ["en"]="nospacing", + ["fr"]="sansespacement", + ["it"]="nospacing", + ["nl"]="geenspatiering", + ["pe"]="بدون‌فضاگذاری", + ["ro"]="nospacing", }, - ["rightpage"]={ - ["cs"]="pravastranka", - ["de"]="rechterseite", - ["en"]="rightpage", - ["fr"]="pagedroite", - ["it"]="paginadestra", - ["nl"]="rechterpagina", - ["pe"]="صفحه‌راست", - ["ro"]="paginadreapta", + ["nostopper"]={ + ["en"]="nostopper", + ["fr"]="sansstoppeur", + ["nl"]="geenafsluiter", }, - ["righttoleft"]={ - ["cs"]="righttoleft", - ["de"]="righttoleft", - ["en"]="righttoleft", - ["fr"]="righttoleft", - ["it"]="righttoleft", - ["nl"]="righttoleft", - ["pe"]="righttoleft", - ["ro"]="righttoleft", + ["not"]={ + ["cs"]="ne", + ["de"]="nicht", + ["en"]="not", + ["fr"]="pas", + ["it"]="non", + ["nl"]="niet", + ["pe"]="بدون", + ["ro"]="nu", }, - ["roman"]={ - ["cs"]="antikva", - ["de"]="antiqua", - ["en"]="roman", - ["fr"]="roman", - ["it"]="roman", - ["nl"]="romaan", - ["pe"]="رومن", - ["ro"]="roman", + ["notation"]={ + ["en"]="notation", + ["fr"]="notation", }, - ["romannumerals"]={ - ["cs"]="rimskecislice", - ["de"]="roemischezahlen", - ["en"]="romannumerals", - ["fr"]="chiffresromains", - ["it"]="numeriromani", - ["nl"]="romeins", - ["pe"]="شماره‌لاتین", - ["ro"]="numereromane", + ["note"]={ + ["en"]="note", + ["fr"]="note", }, - ["rotate"]={ - ["cs"]="otoc", - ["de"]="drehe", - ["en"]="rotate", - ["fr"]="oriente", - ["it"]="ruota", - ["nl"]="roteer", - ["pe"]="دوران", - ["ro"]="rotit", + ["nothanging"]={ + ["cs"]="nothanging", + ["de"]="nothanging", + ["en"]="nothanging", + ["fr"]="sanssuspension", + ["it"]="nonsospeso", + ["nl"]="niethangend", + ["pe"]="بدون‌آویزان‌کردن", + ["ro"]="nothanging", }, - ["rotated"]={ - ["cs"]="otoceno", - ["de"]="gedreht", - ["en"]="rotated", - ["fr"]="tourne", - ["it"]="ruotato", - ["nl"]="geroteerd", - ["pe"]="دوران‌یافته", - ["ro"]="rotat", + ["nothyphenated"]={ + ["cs"]="nothyphenated", + ["de"]="nothyphenated", + ["en"]="nothyphenated", + ["fr"]="sanscesure", + ["it"]="nonsillabato", + ["nl"]="nietafgebroken", + ["pe"]="بدون‌شکست", + ["ro"]="nedespsilabe", }, - ["round"]={ - ["cs"]="zaobleny", - ["de"]="rund", - ["en"]="round", - ["fr"]="rond", - ["it"]="rotondo", - ["nl"]="rond", - ["pe"]="گرد", - ["ro"]="rotund", + ["notjoinedup"]={ + ["en"]="notjoinedup", + ["fr"]="passansespaceentre", + ["nl"]="nietaansluitend", }, - ["row"]={ - ["cs"]="row", - ["de"]="row", - ["en"]="row", - ["fr"]="rang", - ["it"]="row", - ["nl"]="rij", - ["pe"]="سطر", - ["ro"]="rand", + ["november"]={ + ["cs"]="listopad", + ["de"]="november", + ["en"]="november", + ["fr"]="novembre", + ["it"]="novembre", + ["nl"]="november", + ["pe"]="نوامبر", + ["ro"]="noiembrie", + }, + ["nowhere"]={ + ["cs"]="nikde", + ["de"]="nirgens", + ["en"]="nowhere", + ["fr"]="nullepart", + ["it"]="danessunaparte", + ["nl"]="nergens", + ["pe"]="هیچ‌حا", + ["ro"]="niciunde", }, - ["rule"]={ - ["cs"]="linka", - ["de"]="linie", - ["en"]="rule", - ["fr"]="regle", - ["it"]="linea", - ["nl"]="lijn", - ["pe"]="خط", - ["ro"]="rigla", + ["nowhite"]={ + ["cs"]="zadnabila", + ["de"]="keinweiss", + ["en"]="nowhite", + ["fr"]="sansblanc", + ["it"]="nobianco", + ["nl"]="geenwit", + ["pe"]="سفید‌نه", + ["ro"]="faraalb", }, - ["samepage"]={ - ["cs"]="stejnastranka", - ["de"]="selbeseite", - ["en"]="samepage", - ["fr"]="memepage", - ["it"]="stessapagina", - ["nl"]="zelfdepagina", - ["pe"]="همان‌صفحه", - ["ro"]="aceeasipagina", + ["number"]={ + ["cs"]="cislo", + ["de"]="nummer", + ["en"]="number", + ["fr"]="numero", + ["it"]="numero", + ["nl"]="nummer", + ["pe"]="شماره", + ["ro"]="numar", }, - ["sans"]={ - ["cs"]="sans", - ["de"]="sans", - ["en"]="sans", - ["fr"]="sans", - ["it"]="sans", - ["nl"]="sans", - ["pe"]="سانز", - ["ro"]="sans", + ["numbers"]={ + ["cs"]="cisla", + ["de"]="ziffern", + ["en"]="numbers", + ["fr"]="numeros", + ["it"]="numeri", + ["nl"]="cijfers", + ["pe"]="شماره‌ها", + ["ro"]="numere", }, - ["sansbold"]={ - ["cs"]="sanstucne", - ["de"]="sansfett", - ["en"]="sansbold", - ["fr"]="sansgras", - ["it"]="sansgrassetto", - ["nl"]="sansvet", - ["pe"]="مشکی‌سانز", - ["ro"]="sansaldin", + ["october"]={ + ["cs"]="rijen", + ["de"]="oktober", + ["en"]="october", + ["fr"]="octobre", + ["it"]="ottobre", + ["nl"]="oktober", + ["pe"]="اکتبر", + ["ro"]="octombrie", }, - ["sansnormal"]={ - ["en"]="sansnormal", + ["odd"]={ + ["cs"]="liche", + ["de"]="ungerade", + ["en"]="odd", + ["fr"]="impair", + ["it"]="dispari", + ["nl"]="oneven", + ["pe"]="فرد", + ["ro"]="impar", }, - ["sansserif"]={ - ["cs"]="bezserifu", - ["de"]="grotesk", - ["en"]="sansserif", - ["fr"]="sansserif", - ["it"]="sansserif", - ["nl"]="schreefloos", - ["pe"]="سانزسریف", - ["ro"]="sansserif", + ["off"]={ + ["cs"]="vyp", + ["de"]="aus", + ["en"]="off", + ["fr"]="arret", + ["it"]="disattivo", + ["nl"]="uit", + ["pe"]="خاموش", + ["ro"]="dezactivat", }, - ["saturday"]={ - ["cs"]="sobota", - ["de"]="samstag", - ["en"]="saturday", - ["fr"]="samedi", - ["it"]="sabato", - ["nl"]="zaterdag", - ["pe"]="شنبه", - ["ro"]="sambata", + ["offset"]={ + ["cs"]="offset", + ["de"]="offset", + ["en"]="offset", + ["fr"]="decalage", + ["it"]="offset", + ["nl"]="offset", + ["pe"]="آفست", + ["ro"]="offset", }, - ["screen"]={ - ["cs"]="rastr", - ["de"]="raster", - ["en"]="screen", - ["fr"]="ecran", - ["it"]="schermo", - ["nl"]="raster", - ["pe"]="پرده", - ["ro"]="ecran", + ["old"]={ + ["cs"]="old", + ["de"]="old", + ["en"]="old", + ["fr"]="ancien", + ["it"]="old", + ["nl"]="oud", + ["pe"]="قدیمی", + ["ro"]="old", }, - ["section"]={ - ["cs"]="sekce", - ["de"]="absatz", - ["en"]="section", - ["fr"]="section", - ["it"]="capoverso", - ["nl"]="paragraaf", - ["pe"]="بخش", - ["ro"]="sectiune", + ["oldstyle"]={ + ["en"]="oldstyle", + ["fr"]="styleancien", }, - ["sectionblockenvironment"]={ - ["cs"]="sectionblockenvironment", - ["de"]="sectionblockenvironment", - ["en"]="sectionblockenvironment", - ["fr"]="environementblocsection", - ["it"]="ambientebloccosezione", - ["nl"]="sectieblokomgeving", - ["pe"]="محیط‌بلوک‌بخش", - ["ro"]="blocsectiuneambient", + ["on"]={ + ["cs"]="zap", + ["de"]="an", + ["en"]="on", + ["fr"]="marche", + ["it"]="attivo", + ["nl"]="aan", + ["pe"]="روی", + ["ro"]="on", }, - ["sectionnumber"]={ - ["cs"]="cislooddilu", - ["de"]="abschnittsnummer", - ["en"]="sectionnumber", - ["fr"]="numerosection", - ["it"]="numerosezione", - ["nl"]="sectienummer", - ["pe"]="شماره‌بخش", - ["ro"]="numarsetiune", + ["one"]={ + ["cs"]="jedna", + ["de"]="eins", + ["en"]="one", + ["fr"]="un", + ["it"]="uno", + ["nl"]="een", + ["pe"]="یک", + ["ro"]="unu", }, - ["see"]={ - ["cs"]="viz", - ["de"]="sieh", - ["en"]="see", - ["fr"]="voit", - ["it"]="vedi", - ["nl"]="zie", - ["pe"]="ببینید", - ["ro"]="vezi", + ["opposite"]={ + ["cs"]="naproti", + ["de"]="gegenueber", + ["en"]="opposite", + ["fr"]="enface", + ["it"]="opposto", + ["nl"]="naast", + ["pe"]="مخالف", + ["ro"]="opus", }, - ["selectfont"]={ - ["en"]="selectfont", + ["ordinal"]={ + ["en"]="ordinal", + ["fr"]="ordinal", }, - ["separator"]={ - ["en"]="separator", - ["nl"]="scheider", + ["outer"]={ + ["cs"]="vnejsi", + ["de"]="aussen", + ["en"]="outer", + ["fr"]="exterieur", + ["it"]="esterno", + ["nl"]="buiten", + ["pe"]="خارجی", + ["ro"]="extern", }, - ["september"]={ - ["cs"]="zari", - ["de"]="september", - ["en"]="september", - ["fr"]="septembre", - ["it"]="settembre", - ["nl"]="september", - ["pe"]="سپتامبر", - ["ro"]="septembrie", + ["outeredge"]={ + ["cs"]="outeredge", + ["de"]="outeredge", + ["en"]="outeredge", + ["fr"]="bordexterieur", + ["it"]="bordoesterno", + ["nl"]="buitenrand", + ["pe"]="لبه‌خارجی", + ["ro"]="outeredge", }, - ["serif"]={ - ["cs"]="serif", - ["de"]="serif", - ["en"]="serif", - ["fr"]="serif", - ["it"]="serif", - ["nl"]="serif", - ["pe"]="سریف", - ["ro"]="serif", + ["outermargin"]={ + ["cs"]="outermargin", + ["de"]="outermargin", + ["en"]="outermargin", + ["fr"]="margeexterieure", + ["it"]="margineesterno", + ["nl"]="buitenmarge", + ["pe"]="حاشیه‌خارجی", + ["ro"]="outermargin", + }, + ["overbar"]={ + ["cs"]="nadtrzeno", + ["de"]="ueberstrichen", + ["en"]="overbar", + ["fr"]="surligner", + ["it"]="sopralinea", + ["nl"]="overstreep", + ["pe"]="میله‌رو", + ["ro"]="barasus", }, - ["serifbold"]={ - ["en"]="serifbold", + ["overbars"]={ + ["cs"]="nadtrzeni", + ["de"]="ueberstreichen", + ["en"]="overbars", + ["fr"]="surlignermots", + ["it"]="sopralinee", + ["nl"]="overstrepen", + ["pe"]="میله‌ها‌رو", + ["ro"]="supralinie", }, - ["serifnormal"]={ - ["en"]="serifnormal", + ["overlay"]={ + ["cs"]="prekryv", + ["de"]="overlay", + ["en"]="overlay", + ["fr"]="superposition", + ["it"]="sovrapponi", + ["nl"]="overlay", + ["pe"]="پوشش", + ["ro"]="overlay", }, - ["serried"]={ - ["cs"]="semknuto", - ["de"]="kleinerabstand", - ["en"]="serried", - ["fr"]="serried", - ["it"]="vicino", - ["nl"]="aanelkaar", - ["pe"]="تنگ‌هم", - ["ro"]="serried", + ["overprint"]={ + ["cs"]="overprint", + ["de"]="overprint", + ["en"]="overprint", + ["fr"]="surimpression", + ["it"]="overprint", + ["nl"]="overprint", + ["pe"]="overprint", + ["ro"]="overprint", }, - ["setups"]={ - ["comment"]="no translations", - ["en"]="setups", + ["overstrike"]={ + ["cs"]="preskrtnuto", + ["de"]="durchgestrichen", + ["en"]="overstrike", + ["fr"]="barrer", + ["it"]="sbarrato", + ["nl"]="doorstreep", + ["pe"]="خط‌زدن", + ["ro"]="liniepeste", }, - ["sheet"]={ - ["cs"]="sheet", - ["de"]="sheet", - ["en"]="sheet", - ["fr"]="sheet", - ["it"]="sheet", - ["nl"]="sheet", - ["pe"]="ورقه", - ["ro"]="sheet", + ["overstrikes"]={ + ["cs"]="preskrtnuti", + ["de"]="durchstreichen", + ["en"]="overstrikes", + ["fr"]="barrermots", + ["it"]="sbarrati", + ["nl"]="doorstrepen", + ["pe"]="خط‌زدنها", + ["ro"]="liniipeste", }, - ["shiftdown"]={ - ["en"]="shiftdown", + ["packed"]={ + ["cs"]="zhustene", + ["de"]="gepackt", + ["en"]="packed", + ["fr"]="sansespaceentreitem", + ["it"]="impaccato", + ["nl"]="opelkaar", + ["pe"]="فشرده", + ["ro"]="impachetat", }, - ["shiftup"]={ - ["en"]="shiftup", + ["page"]={ + ["cs"]="stranka", + ["de"]="seite", + ["en"]="page", + ["fr"]="page", + ["it"]="pagina", + ["nl"]="pagina", + ["pe"]="صفحه", + ["ro"]="pagina", }, - ["short"]={ - ["cs"]="short", - ["de"]="kurz", - ["en"]="short", - ["fr"]="short", - ["it"]="short", - ["nl"]="kort", - ["ro"]="short", + ["pagecomment"]={ + ["cs"]="komentarstranky", + ["de"]="pagecomment", + ["en"]="pagecomment", + ["fr"]="commentairepage", + ["it"]="commentopagina", + ["nl"]="paginacommentaar", + ["pe"]="توضیح‌صفحه", + ["ro"]="comentariupagina", }, - ["simplefonts"]={ - ["en"]="simplefonts", + ["pagenumber"]={ + ["cs"]="cislostranky", + ["de"]="seitennummer", + ["en"]="pagenumber", + ["fr"]="numeropage", + ["it"]="numeropagina", + ["nl"]="paginanummer", + ["pe"]="شماره‌صفحه", + ["ro"]="numarpagina", }, - ["simplelist"]={ - ["en"]="simplelist", + ["paper"]={ + ["cs"]="papir", + ["de"]="papier", + ["en"]="paper", + ["fr"]="papier", + ["it"]="carta", + ["nl"]="papier", + ["pe"]="برگ", + ["ro"]="foaie", }, - ["singlesided"]={ - ["cs"]="jednostranne", - ["de"]="einzelseitig", - ["en"]="singlesided", - ["fr"]="recto", - ["it"]="facciasingola", - ["nl"]="enkelzijdig", - ["pe"]="یک‌رو", - ["ro"]="ofata", + ["paragraph"]={ + ["cs"]="odstavec", + ["de"]="absatz", + ["en"]="paragraph", + ["fr"]="paragraphe", + ["it"]="capoverso", + ["nl"]="alinea", + ["pe"]="پاراگراف", + ["ro"]="paragraf", }, - ["slanted"]={ - ["cs"]="sklonene", - ["de"]="geneigt", - ["en"]="slanted", - ["fr"]="incline", - ["it"]="inclinato", - ["nl"]="schuin", - ["pe"]="خوابیده", - ["ro"]="inclinat", + ["part"]={ + ["cs"]="cast", + ["de"]="teil", + ["en"]="part", + ["fr"]="partie", + ["it"]="parte", + ["nl"]="deel", + ["pe"]="قسمت", + ["ro"]="parte", }, - ["slantedbold"]={ - ["cs"]="sklonenetucne", - ["de"]="geneigtfett", - ["en"]="slantedbold", - ["fr"]="grasincline", - ["it"]="inclinatograssetto", - ["nl"]="schuinvet", - ["pe"]="مشکی‌خوابیده", - ["ro"]="inclinataldin", + ["positive"]={ + ["cs"]="positiv", + ["de"]="positiv", + ["en"]="positive", + ["fr"]="positif", + ["it"]="positivo", + ["nl"]="positief", + ["pe"]="مثبت", + ["ro"]="positiv", }, - ["small"]={ - ["cs"]="male", - ["de"]="klein", - ["en"]="small", - ["fr"]="petit", - ["it"]="piccolo", - ["nl"]="klein", - ["pe"]="کوچک", - ["ro"]="mic", + ["postponing"]={ + ["cs"]="odlozit", + ["de"]="verschieben", + ["en"]="postponing", + ["fr"]="report", + ["it"]="posporre", + ["nl"]="uitstellen", + ["pe"]="تاخیر", + ["ro"]="postponing", }, - ["smallbodyfont"]={ - ["cs"]="smallbodyfont", - ["de"]="smallbodyfont", - ["en"]="smallbodyfont", - ["fr"]="petitepolicecorps", - ["it"]="piccolofontdelcorpo", - ["nl"]="kleinkorps", - ["pe"]="قلم‌بدنه‌کوچک", - ["ro"]="smallbodyfont", + ["postscript"]={ + ["cs"]="postscript", + ["de"]="postscript", + ["en"]="postscript", + ["fr"]="postscript", + ["it"]="postscript", + ["nl"]="postscript", + ["pe"]="پست‌اسکریپت", + ["ro"]="postscript", }, - ["smallbold"]={ - ["cs"]="maletucne", - ["de"]="kleinfett", - ["en"]="smallbold", - ["fr"]="graspetit", - ["it"]="piccolograssetto", - ["nl"]="kleinvet", - ["pe"]="مشکی‌کوچک", - ["ro"]="micaldin", + ["precedingpage"]={ + ["en"]="precedingpage", + ["fr"]="pageantecedent", + ["nl"]="voorafgaandepagina", }, - ["smallbolditalic"]={ - ["cs"]="maletucnekurzivni", - ["de"]="kleinfettitalic", - ["en"]="smallbolditalic", - ["fr"]="italiquegraspetit", - ["it"]="piccolograssettocorsivo", - ["nl"]="kleinvetitalic", - ["pe"]="ایتالیک‌مشکی‌کوچک", - ["ro"]="micaldininclinat", + ["preference"]={ + ["cs"]="nastaveni", + ["de"]="einstellung", + ["en"]="preference", + ["fr"]="preference", + ["it"]="preferenza", + ["nl"]="voorkeur", + ["pe"]="ترجیح", + ["ro"]="preferinta", }, - ["smallboldslanted"]={ - ["cs"]="maletucnesklonene", - ["de"]="kleinfettgeneigt", - ["en"]="smallboldslanted", - ["fr"]="inclinegraspetit", - ["it"]="piccolograssettoinclinato", - ["nl"]="kleinvetschuin", - ["pe"]="خوابیده‌مشکی‌کوچک", - ["ro"]="micaldininclinat", + ["preview"]={ + ["cs"]="nahled", + ["de"]="vorschau", + ["en"]="preview", + ["fr"]="apercu", + ["it"]="anteprima", + ["nl"]="preview", + ["pe"]="پیش‌دید", + ["ro"]="previzualizare", + }, + ["previous"]={ + ["cs"]="predchozi", + ["de"]="vorig", + ["en"]="previous", + ["fr"]="precedent", + ["it"]="precedente", + ["nl"]="vorige", + ["pe"]="قبلی", + ["ro"]="precedent", }, - ["smallcaps"]={ - ["cs"]="kapitalky", - ["de"]="smallcaps", - ["en"]="smallcaps", - ["fr"]="petitescapitales", - ["it"]="maiuscoletto", - ["nl"]="smallcaps", - ["pe"]="smallcaps", - ["ro"]="majusculemici", + ["previousevenpage"]={ + ["cs"]="predchozisudastranka", + ["de"]="vorigegeradeseite", + ["en"]="previousevenpage", + ["fr"]="pagepaireprecedente", + ["it"]="paginapariprecedente", + ["nl"]="vorigeevenpagina", + ["pe"]="صفحه‌زوج‌قبلی", + ["ro"]="paginaparaprecedenta", }, - ["smaller"]={ - ["en"]="smaller", - ["nl"]="kleiner", + ["previousoddpage"]={ + ["cs"]="predchozilichastranka", + ["de"]="vorigeungeradeseite", + ["en"]="previousoddpage", + ["fr"]="pageimpaireprecedente", + ["it"]="paginadispariprecedente", + ["nl"]="vorigeonevenpagina", + ["pe"]="صفحه‌فردقبلی", + ["ro"]="paginaimparaprecedenta", }, - ["smallitalic"]={ - ["cs"]="malekurzivni", - ["de"]="kleinitalic", - ["en"]="smallitalic", - ["fr"]="italiquepetit", - ["it"]="piccolocorsivo", - ["nl"]="kleinitalic", - ["pe"]="ایتالیک‌کوچک", - ["ro"]="micitalic", + ["previouspage"]={ + ["cs"]="predchozistranka", + ["de"]="vorigeseite", + ["en"]="previouspage", + ["fr"]="pageprecedente", + ["it"]="paginaprecedente", + ["nl"]="vorigepagina", + ["pe"]="صفحه‌قبلی", + ["ro"]="paginaanterioara", }, - ["smallitalicbold"]={ - ["cs"]="malekurzivnitucne", - ["de"]="kleinitalicfett", - ["en"]="smallitalicbold", - ["fr"]="grasitaliquepetit", - ["it"]="piccolocorsivograssetto", - ["nl"]="kleinitalicvet", - ["pe"]="مشکی‌ایتالیک‌کوچک", - ["ro"]="micitalicaldin", + ["previoussubpage"]={ + ["cs"]="predchozipodstranka", + ["de"]="vorigeunterseite", + ["en"]="previoussubpage", + ["fr"]="souspageprecedente", + ["it"]="sottopaginaprecedente", + ["nl"]="vorigesubpagina", + ["pe"]="زیرصفحه‌قبلی", + ["ro"]="subpaginaanterioara", }, - ["smallnormal"]={ - ["cs"]="malenormalni", - ["de"]="kleinnormal", - ["en"]="smallnormal", - ["fr"]="normalpetit", - ["it"]="piccolonormale", - ["nl"]="kleinnormaal", - ["pe"]="نرمال‌کوچک", - ["ro"]="micnormal", + ["print"]={ + ["en"]="print", + ["fr"]="imprimer", + ["nl"]="print", }, - ["smallslanted"]={ - ["cs"]="malesklonene", - ["de"]="kleingeneigt", - ["en"]="smallslanted", - ["fr"]="inclinepetit", - ["it"]="piccoloinclinato", - ["nl"]="kleinschuin", - ["pe"]="خوابیده‌کوچک", - ["ro"]="micinclinat", + ["printable"]={ + ["cs"]="tisknutelne", + ["de"]="druckbar", + ["en"]="printable", + ["fr"]="imprimable", + ["it"]="stampabile", + ["nl"]="printbaar", + ["pe"]="قابل‌چاپ", + ["ro"]="tiparibil", }, - ["smallslantedbold"]={ - ["cs"]="malesklonenetucne", - ["de"]="kleingeneigtfett", - ["en"]="smallslantedbold", - ["fr"]="grasinclinepetit", - ["it"]="piccoloinclinatograssetto", - ["nl"]="kleinschuinvet", - ["pe"]="مشکی‌خوابیده‌کوچک", - ["ro"]="micinclinataldin", + ["process"]={ + ["cs"]="process", + ["de"]="process", + ["en"]="process", + ["fr"]="traiter", + ["it"]="process", + ["nl"]="proces", + ["pe"]="پردازش", + ["ro"]="process", }, - ["smalltype"]={ - ["cs"]="maletype", - ["de"]="kleintippen", - ["en"]="smalltype", - ["fr"]="petittype", - ["it"]="piccolotype", - ["nl"]="kleintype", - ["pe"]="تایپ‌کوچک", - ["ro"]="mictype", + ["product"]={ + ["cs"]="produkt", + ["de"]="produkt", + ["en"]="product", + ["fr"]="produit", + ["it"]="prodotto", + ["nl"]="produkt", + ["pe"]="محصول", + ["ro"]="produs", }, - ["somewhere"]={ - ["cs"]="nekde", - ["de"]="irgendwo", - ["en"]="somewhere", - ["fr"]="qqpart", - ["it"]="daqualcheparte", - ["nl"]="ergens", - ["pe"]="جایی", - ["ro"]="undeva", + ["program"]={ + ["cs"]="program", + ["de"]="programm", + ["en"]="program", + ["fr"]="programme", + ["it"]="programma", + ["nl"]="programma", + ["pe"]="برنامه", + ["ro"]="program", }, - ["sorted"]={ - ["cs"]="tridene", - ["de"]="sortiert", - ["en"]="sorted", - ["fr"]="trie", - ["it"]="ordinato", - ["nl"]="gesorteerd", - ["pe"]="مرتب", - ["ro"]="sortat", + ["project"]={ + ["cs"]="projekt", + ["de"]="projekt", + ["en"]="project", + ["fr"]="projet", + ["it"]="progetto", + ["nl"]="project", + ["pe"]="پروژه", + ["ro"]="proiect", }, - ["sorting"]={ - ["en"]="sorting", + ["protected"]={ + ["cs"]="chranene", + ["de"]="geschuetzt", + ["en"]="protected", + ["fr"]="protege", + ["it"]="protetto", + ["nl"]="beschermd", + ["pe"]="حفاظت‌شده", + ["ro"]="protejat", }, - ["space"]={ - ["cs"]="mezera", - ["de"]="spatium", - ["en"]="space", - ["fr"]="espace", - ["it"]="spazio", - ["nl"]="spatie", - ["pe"]="فضا", - ["ro"]="spatiu", + ["quadruple"]={ + ["cs"]="ctyrnasobny", + ["de"]="viertel", + ["en"]="quadruple", + ["fr"]="quadruple", + ["it"]="quadruplo", + ["nl"]="viertal", + ["pe"]="quadruple", + ["ro"]="cvadrupul", }, - ["spacing"]={ - ["cs"]="mezerovani", - ["de"]="spatiumausgleich", - ["en"]="spacing", - ["fr"]="espacement", - ["it"]="spaziatura", - ["nl"]="spatiering", - ["pe"]="فضاگذاری", - ["ro"]="spatiere", + ["quarterline"]={ + ["en"]="quarterline", + ["fr"]="quartdeligne", + ["nl"]="kwartregel", }, - ["speech"]={ - ["cs"]="speech", - ["de"]="speech", - ["en"]="speech", - ["fr"]="discours", - ["it"]="speech", - ["nl"]="spraak", - ["pe"]="سخنرانی", - ["ro"]="speech", + ["quotation"]={ + ["cs"]="citace", + ["de"]="zitat", + ["en"]="quotation", + ["fr"]="citation", + ["it"]="citazione", + ["nl"]="citaat", + ["pe"]="نقل‌قول", + ["ro"]="citat", }, - ["split"]={ - ["cs"]="split", - ["de"]="split", - ["en"]="split", - ["fr"]="split", - ["it"]="separa", - ["nl"]="splitsen", - ["pe"]="شکافتن", - ["ro"]="split", + ["quote"]={ + ["cs"]="citovat", + ["de"]="zitieren", + ["en"]="quote", + ["fr"]="citer", + ["it"]="menzione", + ["nl"]="citeer", + ["pe"]="نقل", + ["ro"]="minicitat", }, - ["spot"]={ - ["cs"]="spot", - ["de"]="spot", - ["en"]="spot", - ["fr"]="spot", - ["it"]="spot", - ["nl"]="spot", - ["pe"]="لکه", - ["ro"]="spot", + ["ran"]={ + ["cs"]="rozsah", + ["de"]="ran", + ["en"]="ran", + ["fr"]="gam", + ["it"]="corse", + ["nl"]="ran", + ["pe"]="برد", + ["ro"]="rulat", }, - ["standard"]={ - ["cs"]="standardni", - ["de"]="standard", - ["en"]="standard", - ["fr"]="standard", - ["it"]="standard", - ["nl"]="standaard", - ["pe"]="استاندارد", - ["ro"]="standard", + ["random"]={ + ["cs"]="nahodny", + ["de"]="zufaellig", + ["en"]="random", + ["fr"]="aleatoire", + ["it"]="casuale", + ["nl"]="willekeurig", + ["pe"]="تصادفی", + ["ro"]="aleator", }, - ["start"]={ - ["cs"]="start", - ["de"]="start", - ["en"]="start", - ["fr"]="demarre", - ["it"]="inizia", - ["nl"]="start", - ["pe"]="شروع", - ["ro"]="start", + ["readonly"]={ + ["cs"]="pouzeprocteni", + ["de"]="nurlesbar", + ["en"]="readonly", + ["fr"]="lectureseule", + ["it"]="solalettura", + ["nl"]="alleenleesbaar", + ["pe"]="تنهاخواندنی", + ["ro"]="readonly", }, - ["starter"]={ - ["en"]="starter", - ["nl"]="opener", + ["rectangular"]={ + ["cs"]="pravouhly", + ["de"]="rechteckig", + ["en"]="rectangular", + ["fr"]="rectangulaire", + ["it"]="rettangolare", + ["nl"]="recht", + ["pe"]="چهارگوشه", + ["ro"]="rectangular", }, - ["sticker"]={ - ["cs"]="sticker", - ["de"]="sticker", - ["en"]="sticker", - ["fr"]="sticker", - ["it"]="sticker", - ["nl"]="sticker", - ["pe"]="دشنه", - ["ro"]="sticker", + ["reference"]={ + ["cs"]="odkaz", + ["de"]="referenz", + ["en"]="reference", + ["fr"]="reference", + ["it"]="riferimento", + ["nl"]="referentie", + ["pe"]="مرجع", + ["ro"]="referinta", }, - ["stop"]={ - ["cs"]="stop", - ["de"]="stop", - ["en"]="stop", - ["fr"]="stoppe", - ["it"]="termina", - ["nl"]="stop", - ["pe"]="پایان", - ["ro"]="stop", + ["referral"]={ + ["cs"]="znacka", + ["de"]="merkmal", + ["en"]="referral", + ["fr"]="redirection", + ["it"]="referral", + ["nl"]="kenmerk", + ["pe"]="مراجعه", + ["ro"]="referinta", }, - ["stopper"]={ - ["cs"]="predel", - ["de"]="trenner", - ["en"]="stopper", - ["fr"]="stopper", - ["it"]="stopper", - ["nl"]="afsluiter", - ["pe"]="ایست", - ["ro"]="stopper", + ["register"]={ + ["cs"]="rejstrik", + ["de"]="register", + ["en"]="register", + ["fr"]="registre", + ["it"]="registro", + ["nl"]="register", + ["pe"]="ثبت", + ["ro"]="registru", }, - ["nostopper"]={ - ["en"]="nostopper", - ["nl"]="geenafsluiter", + ["regular"]={ + ["cs"]="pravidelne", + ["de"]="regular", + ["en"]="regular", + ["fr"]="ordinaire", + ["it"]="regolare", + ["nl"]="regular", + ["pe"]="منظم", + ["ro"]="regular", }, - ["stretch"]={ - ["cs"]="natahnout", - ["de"]="strecken", - ["en"]="stretch", - ["fr"]="etire", - ["it"]="dilata", - ["nl"]="rek", - ["pe"]="بکش", - ["ro"]="dilatat", + ["relative"]={ + ["cs"]="relativni", + ["de"]="relativ", + ["en"]="relative", + ["fr"]="relatif", + ["it"]="relativo", + ["nl"]="relatief", + ["pe"]="نسبی", + ["ro"]="relativ", }, - ["stretched"]={ - ["en"]="stretched", + ["repeat"]={ + ["cs"]="opakovat", + ["de"]="wiederholen", + ["en"]="repeat", + ["fr"]="repeter", + ["it"]="ripeti", + ["nl"]="herhaal", + ["pe"]="تکرار", + ["ro"]="repetat", }, - ["strict"]={ - ["cs"]="striktni", - ["de"]="streng", - ["en"]="strict", - ["fr"]="strict", - ["it"]="rigido", - ["nl"]="streng", - ["pe"]="اکید", - ["ro"]="strict", + ["required"]={ + ["cs"]="pozadovane", + ["de"]="obligatorisch", + ["en"]="required", + ["fr"]="requis", + ["it"]="richiestp", + ["nl"]="verplicht", + ["pe"]="موردنیاز", + ["ro"]="obligatoriu", }, - ["strong"]={ - ["cs"]="strong", - ["de"]="strong", - ["en"]="strong", - ["fr"]="strong", - ["it"]="strong", - ["nl"]="sterk", - ["pe"]="محکم", - ["ro"]="strong", + ["reset"]={ + ["cs"]="reset", + ["de"]="zuruecksetzten", + ["en"]="reset", + ["fr"]="raz", + ["it"]="reimposta", + ["nl"]="reset", + ["pe"]="بازنشانی", + ["ro"]="reset", }, - ["strut"]={ - ["cs"]="strut", - ["de"]="strut", - ["en"]="strut", - ["fr"]="strut", - ["it"]="strut", - ["nl"]="strut", - ["pe"]="بست", - ["ro"]="strut", + ["reverse"]={ + ["cs"]="reverse", + ["de"]="reverse", + ["en"]="reverse", + ["fr"]="inverser", + ["it"]="invertito", + ["nl"]="omgekeerd", + ["pe"]="برعکس", + ["ro"]="reverse", }, - ["sub"]={ - ["cs"]="pod", - ["de"]="unter", - ["en"]="sub", - ["fr"]="sous", - ["it"]="sotto", - ["nl"]="sub", - ["pe"]="زیر", - ["ro"]="sub", + ["right"]={ + ["cs"]="vpravo", + ["de"]="rechts", + ["en"]="right", + ["fr"]="droite", + ["it"]="destra", + ["nl"]="rechts", + ["pe"]="راست", + ["ro"]="dreapta", }, - ["subbackward"]={ - ["cs"]="podzpet", - ["de"]="unterrueckwaerts", - ["en"]="subbackward", - ["fr"]="sousretourarriere", - ["it"]="sottoindietro", - ["nl"]="subachteruit", - ["pe"]="زیرعقب‌گرد", - ["ro"]="subinapoi", + ["rightedge"]={ + ["cs"]="pravahrana", + ["de"]="rechterkante", + ["en"]="rightedge", + ["fr"]="borddroit", + ["it"]="bordodestro", + ["nl"]="rechterrand", + ["pe"]="لبه‌راست", + ["ro"]="borduradreapta", }, - ["subformula"]={ - ["cs"]="subrovnice", - ["de"]="subformel", - ["en"]="subformula", - ["fr"]="subformule", - ["it"]="subformula", - ["nl"]="subformule", - ["pe"]="زیرفرمول", - ["ro"]="subformula", + ["righthanging"]={ + ["cs"]="righthanging", + ["de"]="righthanging", + ["en"]="righthanging", + ["fr"]="suspensiondroite", + ["it"]="righthanging", + ["nl"]="rechtshangend", + ["pe"]="آویزان‌کردن‌راست", + ["ro"]="righthanging", }, - ["subforward"]={ - ["cs"]="podvpred", - ["de"]="untervorwaerts", - ["en"]="subforward", - ["fr"]="sousavance", - ["it"]="sottoavanti", - ["nl"]="subvooruit", - ["pe"]="زیرجلوگرد", - ["ro"]="subavans", + ["rightmargin"]={ + ["cs"]="pravyokraj", + ["de"]="rechterrand", + ["en"]="rightmargin", + ["fr"]="margedroite", + ["it"]="marginedestro", + ["nl"]="rechtermarge", + ["pe"]="حاشیه‌راست", + ["ro"]="marginedreapta", }, - ["subject"]={ - ["cs"]="tema", - ["de"]="thema", - ["en"]="subject", - ["fr"]="sujet", - ["it"]="argomento", - ["nl"]="onderwerp", - ["pe"]="موضوع", - ["ro"]="subiect", + ["rightpage"]={ + ["cs"]="pravastranka", + ["de"]="rechterseite", + ["en"]="rightpage", + ["fr"]="surpagedroite", + ["it"]="paginadestra", + ["nl"]="rechterpagina", + ["pe"]="صفحه‌راست", + ["ro"]="paginadreapta", }, - ["subpage"]={ - ["cs"]="podstranka", - ["de"]="unterseite", - ["en"]="subpage", - ["fr"]="souspage", - ["it"]="sottopagina", - ["nl"]="subpagina", - ["pe"]="زیرصفحه", - ["ro"]="subpagina", + ["righttoleft"]={ + ["cs"]="righttoleft", + ["de"]="righttoleft", + ["en"]="righttoleft", + ["fr"]="droiteagauche", + ["it"]="righttoleft", + ["nl"]="righttoleft", + ["pe"]="righttoleft", + ["ro"]="righttoleft", }, - ["subs"]={ - ["en"]="subs", + ["roman"]={ + ["cs"]="antikva", + ["de"]="antiqua", + ["en"]="roman", + ["fr"]="romain", + ["it"]="roman", + ["nl"]="romaan", + ["pe"]="رومن", + ["ro"]="roman", }, - ["subsection"]={ - ["cs"]="podsekce", - ["de"]="unterabsatz", - ["en"]="subsection", - ["fr"]="soussection", - ["it"]="sottocapoverso", - ["nl"]="subparagraaf", - ["pe"]="زیربخش", - ["ro"]="subsectiune", + ["romannumerals"]={ + ["cs"]="rimskecislice", + ["de"]="roemischezahlen", + ["en"]="romannumerals", + ["fr"]="chiffresromains", + ["it"]="numeriromani", + ["nl"]="romeins", + ["pe"]="شماره‌لاتین", + ["ro"]="numereromane", }, - ["subsubject"]={ - ["cs"]="podtema", - ["de"]="unterthema", - ["en"]="subsubject", - ["fr"]="soussujet", - ["it"]="sottoargomento", - ["nl"]="subonderwerp", - ["pe"]="زیرموضوع", - ["ro"]="subsubiect", + ["rotate"]={ + ["cs"]="otoc", + ["de"]="drehe", + ["en"]="rotate", + ["fr"]="tourner", + ["it"]="ruota", + ["nl"]="roteer", + ["pe"]="دوران", + ["ro"]="rotit", }, - ["subsubsection"]={ - ["cs"]="podpodsekce", - ["de"]="unterunterabsatz", - ["en"]="subsubsection", - ["fr"]="soussoussection", - ["it"]="sottosottocapoverso", - ["nl"]="subsubparagraaf", - ["pe"]="زیرزیربخش", - ["ro"]="subsubsectiune", + ["rotated"]={ + ["cs"]="otoceno", + ["de"]="gedreht", + ["en"]="rotated", + ["fr"]="tourne", + ["it"]="ruotato", + ["nl"]="geroteerd", + ["pe"]="دوران‌یافته", + ["ro"]="rotat", }, - ["subsubsubject"]={ - ["cs"]="podpodtema", - ["de"]="unterunterthema", - ["en"]="subsubsubject", - ["fr"]="soussoussujet", - ["it"]="sottosottoargomento", - ["nl"]="subsubonderwerp", - ["pe"]="زیرزیرموضوع", - ["ro"]="subsubsubiect", + ["round"]={ + ["cs"]="zaobleny", + ["de"]="rund", + ["en"]="round", + ["fr"]="rond", + ["it"]="rotondo", + ["nl"]="rond", + ["pe"]="گرد", + ["ro"]="rotund", }, - ["subsubsubsection"]={ - ["cs"]="podpodpodsekce", - ["de"]="unterunterunterabsatz", - ["en"]="subsubsubsection", - ["fr"]="soussoussoussection", - ["it"]="sottosottosottocapoverso", - ["nl"]="subsubsubparagraaf", - ["pe"]="زیرزیرزیربخش", - ["ro"]="subsubsubsectiune", + ["row"]={ + ["cs"]="row", + ["de"]="row", + ["en"]="row", + ["fr"]="rang", + ["it"]="row", + ["nl"]="rij", + ["pe"]="سطر", + ["ro"]="rand", }, - ["subsubsubsubject"]={ - ["cs"]="podpodpodtema", - ["de"]="unterunterunterthema", - ["en"]="subsubsubsubject", - ["fr"]="soussoussoussujet", - ["it"]="sottosottosottoargomento", - ["nl"]="subsubsubonderwerp", - ["pe"]="زیرزیرزیرموضوع", - ["ro"]="subsubsubsubiect", + ["rule"]={ + ["cs"]="linka", + ["de"]="linie", + ["en"]="rule", + ["fr"]="trait", + ["it"]="linea", + ["nl"]="lijn", + ["pe"]="خط", + ["ro"]="rigla", }, - ["subsubsubsubsection"]={ - ["cs"]="podpodpodpodsekce", - ["de"]="unterunterunterunterabsatz", - ["en"]="subsubsubsubsection", - ["fr"]="soussoussoussoussection", - ["it"]="sottosottosottosottocapoverso", - ["nl"]="subsubsubsubparagraaf", - ["pe"]="زیرزیرزیرزیربخش", - ["ro"]="subsubsubsubsectiune", + ["samepage"]={ + ["cs"]="stejnastranka", + ["de"]="selbeseite", + ["en"]="samepage", + ["fr"]="memepage", + ["it"]="stessapagina", + ["nl"]="zelfdepagina", + ["pe"]="همان‌صفحه", + ["ro"]="aceeasipagina", }, - ["subsubsubsubsubject"]={ - ["cs"]="podpodpodpodtema", - ["de"]="unterunterunterunterthema", - ["en"]="subsubsubsubsubject", - ["fr"]="soussoussoussoussujet", - ["it"]="sottosottosottosottoargomento", - ["nl"]="subsubsubsubonderwerp", - ["pe"]="زیرزیرزیرزیرموضوع", - ["ro"]="subsubsubsubsubiect", + ["sans"]={ + ["cs"]="sans", + ["de"]="sans", + ["en"]="sans", + ["fr"]="sans", + ["it"]="sans", + ["nl"]="sans", + ["pe"]="سانز", + ["ro"]="sans", }, - ["subsubsubsubsubsection"]={ - ["cs"]="podpodpodpodpodsekce", - ["de"]="unterunterunterunterunterabsatz", - ["en"]="subsubsubsubsubsection", - ["fr"]="soussoussoussoussoussection", - ["it"]="sottosottosottosottosottocapoverso", - ["nl"]="subsubsubsubsubparagraaf", - ["pe"]="زیرزیرزیرزیرزیربخش", - ["ro"]="subsubsubsubsubsectiune", + ["sansbold"]={ + ["cs"]="sanstucne", + ["de"]="sansfett", + ["en"]="sansbold", + ["fr"]="sansserifbold", + ["it"]="sansgrassetto", + ["nl"]="sansvet", + ["pe"]="مشکی‌سانز", + ["ro"]="sansaldin", }, - ["subsubsubsubsubsubject"]={ - ["cs"]="podpodpodpodpodtema", - ["de"]="unterunterunterunterunterthema", - ["en"]="subsubsubsubsubsubject", - ["fr"]="soussoussoussoussoussujet", - ["it"]="sottosottosottosottosottoargomento", - ["nl"]="subsubsubsubsubonderwerp", - ["pe"]="زیرزیرزیرزیرزیرموضوع", - ["ro"]="subsubsubsubsubsubiect", + ["sansnormal"]={ + ["en"]="sansnormal", + ["fr"]="normalsans", }, - ["subsubsubsubsubsubsection"]={ - ["cs"]="podpodpodpodpodpodsekce", - ["de"]="unterunterunterunterunterunterabsatz", - ["en"]="subsubsubsubsubsubsection", - ["fr"]="soussoussoussoussoussoussection", - ["it"]="sottosottosottosottosottosottocapoverso", - ["nl"]="subsubsubsubsubsubparagraaf", - ["pe"]="زیرزیرزیرزیرزیرزیربخش", - ["ro"]="subsubsubsubsubsubsectiune", + ["sansserif"]={ + ["cs"]="bezserifu", + ["de"]="grotesk", + ["en"]="sansserif", + ["fr"]="sansserif", + ["it"]="sansserif", + ["nl"]="schreefloos", + ["pe"]="سانزسریف", + ["ro"]="sansserif", }, - ["subsubsubsubsubsubsubject"]={ - ["cs"]="podpodpodpodpodpodtema", - ["de"]="unterunterunterunterunterunterthema", - ["en"]="subsubsubsubsubsubsubject", - ["fr"]="soussoussoussoussoussoussujet", - ["it"]="sottosottosottosottosottosottoargomento", - ["nl"]="subsubsubsubsubsubonderwerp", - ["pe"]="زیرزیرزیرزیرزیرزیرموضوع", - ["ro"]="subsubsubsubsubsubsubiect", + ["saturday"]={ + ["cs"]="sobota", + ["de"]="samstag", + ["en"]="saturday", + ["fr"]="samedi", + ["it"]="sabato", + ["nl"]="zaterdag", + ["pe"]="شنبه", + ["ro"]="sambata", + }, + ["screen"]={ + ["cs"]="rastr", + ["de"]="raster", + ["en"]="screen", + ["fr"]="ecran", + ["it"]="schermo", + ["nl"]="raster", + ["pe"]="پرده", + ["ro"]="ecran", }, - ["subsubsubsubsubsubsubsection"]={ - ["cs"]="podpodpodpodpodpodpodsekce", - ["de"]="unterunterunterunterunterunterunterabsatz", - ["en"]="subsubsubsubsubsubsubsection", - ["fr"]="soussoussoussoussoussoussoussection", - ["it"]="sottosottosottosottosottosottosottocapoverso", - ["nl"]="subsubsubsubsubsubsubparagraaf", - ["pe"]="زیرزیرزیرزیرزیرزیرزیربخش", - ["ro"]="subsubsubsubsubsubsubsectiune", + ["section"]={ + ["cs"]="sekce", + ["de"]="absatz", + ["en"]="section", + ["fr"]="section", + ["it"]="capoverso", + ["nl"]="paragraaf", + ["pe"]="بخش", + ["ro"]="sectiune", }, - ["subsubsubsubsubsubsubsubject"]={ - ["cs"]="podpodpodpodpodpodpodtema", - ["de"]="unterunterunterunterunterunterunterthema", - ["en"]="subsubsubsubsubsubsubsubject", - ["fr"]="soussoussoussoussoussoussoussujet", - ["it"]="sottosottosottosottosottosottosottoargomento", - ["nl"]="subsubsubsubsubsubsubonderwerp", - ["pe"]="زیرزیرزیرزیرزیرزیرزیرموضوع", - ["ro"]="subsubsubsubsubsubsubsubiect", + ["sectionblockenvironment"]={ + ["cs"]="sectionblockenvironment", + ["de"]="sectionblockenvironment", + ["en"]="sectionblockenvironment", + ["fr"]="environnementblocsection", + ["it"]="ambientebloccosezione", + ["nl"]="sectieblokomgeving", + ["pe"]="محیط‌بلوک‌بخش", + ["ro"]="blocsectiuneambient", }, - ["subsubsubsubsubsubsubsubsection"]={ - ["cs"]="podpodpodpodpodpodpodpodsekce", - ["de"]="unterunterunterunterunterunterunterunterabsatz", - ["en"]="subsubsubsubsubsubsubsubsection", - ["fr"]="soussoussoussoussoussoussoussoussection", - ["it"]="sottosottosottosottosottosottosottosottocapoverso", - ["nl"]="subsubsubsubsubsubsubsubparagraaf", - ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیربخش", - ["ro"]="subsubsubsubsubsubsubsubsectiune", + ["sectionnumber"]={ + ["cs"]="cislooddilu", + ["de"]="abschnittsnummer", + ["en"]="sectionnumber", + ["fr"]="numerosection", + ["it"]="numerosezione", + ["nl"]="sectienummer", + ["pe"]="شماره‌بخش", + ["ro"]="numarsetiune", }, - ["subsubsubsubsubsubsubsubsubject"]={ - ["cs"]="podpodpodpodpodpodpodpodtema", - ["de"]="unterunterunterunterunterunterunterunterthema", - ["en"]="subsubsubsubsubsubsubsubsubject", - ["fr"]="soussoussoussoussoussoussoussoussujet", - ["it"]="sottosottosottosottosottosottosottosottoargomento", - ["nl"]="subsubsubsubsubsubsubsubonderwerp", - ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیرموضوع", - ["ro"]="subsubsubsubsubsubsubsubsubiect", + ["see"]={ + ["cs"]="viz", + ["de"]="sieh", + ["en"]="see", + ["fr"]="voir", + ["it"]="vedi", + ["nl"]="zie", + ["pe"]="ببینید", + ["ro"]="vezi", }, - ["subsubsubsubsubsubsubsubsubsection"]={ - ["cs"]="podpodpodpodpodpodpodpodpodsekce", - ["de"]="unterunterunterunterunterunterunterunterunterabsatz", - ["en"]="subsubsubsubsubsubsubsubsubsection", - ["fr"]="soussoussoussoussoussoussoussoussoussection", - ["it"]="sottosottosottosottosottosottosottosottosottocapoverso", - ["nl"]="subsubsubsubsubsubsubsubsubparagraaf", - ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیرزیربخش", - ["ro"]="subsubsubsubsubsubsubsubsubsectiune", + ["selectfont"]={ + ["en"]="selectfont", + ["fr"]="selectionnerpolice", }, - ["subsubsubsubsubsubsubsubsubsubject"]={ - ["cs"]="podpodpodpodpodpodpodpodpodtema", - ["de"]="unterunterunterunterunterunterunterunterunterthema", - ["en"]="subsubsubsubsubsubsubsubsubsubject", - ["fr"]="soussoussoussoussoussoussoussoussoussujet", - ["it"]="sottosottosottosottosottosottosottosottosottoargomento", - ["nl"]="subsubsubsubsubsubsubsubsubonderwerp", - ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیرزیرموضوع", - ["ro"]="subsubsubsubsubsubsubsubsubsubiect", + ["separator"]={ + ["en"]="separator", + ["fr"]="separateur", + ["nl"]="scheider", }, - ["sunday"]={ - ["cs"]="nedele", - ["de"]="sonntag", - ["en"]="sunday", - ["fr"]="dimanche", - ["it"]="domenica", - ["nl"]="zondag", - ["pe"]="یک‌شنبه", - ["ro"]="duminica", + ["september"]={ + ["cs"]="zari", + ["de"]="september", + ["en"]="september", + ["fr"]="septembre", + ["it"]="settembre", + ["nl"]="september", + ["pe"]="سپتامبر", + ["ro"]="septembrie", }, - ["support"]={ - ["cs"]="podpora", - ["de"]="support", - ["en"]="support", - ["fr"]="support", - ["it"]="supporto", - ["nl"]="support", - ["pe"]="حمایت", - ["ro"]="suport", + ["serif"]={ + ["cs"]="serif", + ["de"]="serif", + ["en"]="serif", + ["fr"]="serif", + ["it"]="serif", + ["nl"]="serif", + ["pe"]="سریف", + ["ro"]="serif", }, - ["sym"]={ - ["cs"]="sym", - ["de"]="sym", - ["en"]="sym", - ["fr"]="sym", - ["it"]="sim", - ["nl"]="sym", - ["pe"]="نم", - ["ro"]="sym", + ["serifbold"]={ + ["en"]="serifbold", + ["fr"]="serifgras", }, - ["symbol"]={ - ["cs"]="symbol", - ["de"]="symbol", - ["en"]="symbol", - ["fr"]="symbole", - ["it"]="simbolo", - ["nl"]="symbool", - ["pe"]="نماد", - ["ro"]="simbol", + ["serifnormal"]={ + ["en"]="serifnormal", + ["fr"]="serifnormal", }, - ["synchronize"]={ - ["cs"]="synchronize", - ["de"]="synchronize", - ["en"]="synchronize", - ["fr"]="synchronize", - ["it"]="synchronize", - ["nl"]="synchroniseer", - ["pe"]="تطابق", - ["ro"]="synchronize", + ["serried"]={ + ["cs"]="semknuto", + ["de"]="kleinerabstand", + ["en"]="serried", + ["fr"]="serre", + ["it"]="vicino", + ["nl"]="aanelkaar", + ["pe"]="تنگ‌هم", + ["ro"]="serried", }, - ["synonym"]={ - ["en"]="synonym", + ["setups"]={ + ["en"]="setups", }, - ["system"]={ - ["cs"]="system", - ["de"]="systeme", - ["en"]="system", - ["fr"]="systeme", - ["it"]="sistema", - ["nl"]="systeem", - ["pe"]="سیستم", - ["ro"]="sistem", + ["seven"]={ + ["cs"]="seven", + ["de"]="sieben", + ["en"]="seven", + ["fr"]="sept", + ["it"]="seven", + ["nl"]="zeven", + ["pe"]="seven", + ["ro"]="seven", }, - ["table"]={ - ["cs"]="tabulka", - ["de"]="tabelle", - ["en"]="table", - ["fr"]="tableau", - ["it"]="tabella", - ["nl"]="tabel", - ["pe"]="جدول", - ["ro"]="tabelul", + ["sheet"]={ + ["cs"]="sheet", + ["de"]="sheet", + ["en"]="sheet", + ["fr"]="feuille", + ["it"]="sheet", + ["nl"]="sheet", + ["pe"]="ورقه", + ["ro"]="sheet", }, - ["tablehead"]={ - ["cs"]="zahlavitabulky", - ["de"]="tabellenueberschrift", - ["en"]="tablehead", - ["fr"]="tetetableau", - ["it"]="testatabella", - ["nl"]="tabelkop", - ["pe"]="سرجدول", - ["ro"]="antettabel", + ["shiftdown"]={ + ["en"]="shiftdown", + ["fr"]="decalerenbas", }, - ["tables"]={ - ["cs"]="tabulky", - ["de"]="tabellen", - ["en"]="tables", - ["fr"]="tables", - ["it"]="tabelle", - ["nl"]="tabellen", - ["pe"]="جدولها", - ["ro"]="tabelele", + ["shiftup"]={ + ["en"]="shiftup", + ["fr"]="decalerenhaut", }, - ["tabletail"]={ - ["cs"]="konectabulky", - ["de"]="tabellenende", - ["en"]="tabletail", - ["fr"]="queuetableau", - ["it"]="codatabella", - ["nl"]="tabelstaart", - ["pe"]="دنباله‌جدول", - ["ro"]="subsoltabel", + ["short"]={ + ["cs"]="short", + ["de"]="kurz", + ["en"]="short", + ["fr"]="court", + ["it"]="short", + ["nl"]="kort", + ["ro"]="short", }, - ["tabulate"]={ - ["cs"]="tabelator", - ["de"]="tabulator", - ["en"]="tabulate", - ["fr"]="tabule", - ["it"]="tabulato", - ["nl"]="tabulatie", - ["pe"]="جدول‌بندی", - ["ro"]="tabulate", + ["simplefonts"]={ + ["en"]="simplefonts", + ["fr"]="policessimple", }, - ["tabulatehead"]={ - ["cs"]="tabulatehead", - ["de"]="tabulatehead", - ["en"]="tabulatehead", - ["fr"]="tetetabule", - ["it"]="testatabulato", - ["nl"]="tabulatiekop", - ["pe"]="سرجدول‌بندی", - ["ro"]="tabulatehead", + ["simplelist"]={ + ["en"]="simplelist", + ["fr"]="listesimple", }, - ["tabulatetail"]={ - ["cs"]="tabulatetail", - ["de"]="tabulatetail", - ["en"]="tabulatetail", - ["fr"]="queuetabule", - ["it"]="codatabulato", - ["nl"]="tabulatiestaart", - ["pe"]="دنباله‌جدول‌بندی", - ["ro"]="tabulatetail", + ["singlesided"]={ + ["cs"]="jednostranne", + ["de"]="einzelseitig", + ["en"]="singlesided", + ["fr"]="recto", + ["it"]="facciasingola", + ["nl"]="enkelzijdig", + ["pe"]="یک‌رو", + ["ro"]="ofata", }, - ["tall"]={ - ["cs"]="vysoko", - ["de"]="lang", - ["en"]="tall", - ["fr"]="long", - ["it"]="alto", - ["nl"]="lang", - ["pe"]="دراز", - ["ro"]="inalt", + ["six"]={ + ["cs"]="six", + ["de"]="sechs", + ["en"]="six", + ["fr"]="six", + ["it"]="six", + ["nl"]="zes", + ["pe"]="six", + ["ro"]="six", }, - ["teletype"]={ - ["cs"]="strojopis", - ["de"]="fernschreiber", - ["en"]="teletype", - ["fr"]="teletype", - ["it"]="teletype", - ["nl"]="teletype", - ["pe"]="دورنگاره", - ["ro"]="teletype", + ["slanted"]={ + ["cs"]="sklonene", + ["de"]="geneigt", + ["en"]="slanted", + ["fr"]="incline", + ["it"]="inclinato", + ["nl"]="schuin", + ["pe"]="خوابیده", + ["ro"]="inclinat", }, - ["temporary"]={ - ["cs"]="docasne", - ["de"]="temporaer", - ["en"]="temporary", - ["fr"]="temporaire", - ["it"]="temporaneo", - ["nl"]="voorlopig", - ["pe"]="موقتی", - ["ro"]="temporar", + ["slantedbold"]={ + ["cs"]="sklonenetucne", + ["de"]="geneigtfett", + ["en"]="slantedbold", + ["fr"]="inclinegras", + ["it"]="inclinatograssetto", + ["nl"]="schuinvet", + ["pe"]="مشکی‌خوابیده", + ["ro"]="inclinataldin", }, - ["test"]={ - ["cs"]="test", - ["de"]="test", - ["en"]="test", - ["fr"]="test", - ["it"]="test", - ["nl"]="test", - ["pe"]="تست", - ["ro"]="test", + ["small"]={ + ["cs"]="male", + ["de"]="klein", + ["en"]="small", + ["fr"]="petit", + ["it"]="piccolo", + ["nl"]="klein", + ["pe"]="کوچک", + ["ro"]="mic", }, - ["text"]={ - ["cs"]="text", - ["de"]="text", - ["en"]="text", - ["fr"]="texte", - ["it"]="testo", - ["nl"]="tekst", - ["pe"]="متن", - ["ro"]="text", + ["smallbodyfont"]={ + ["cs"]="smallbodyfont", + ["de"]="smallbodyfont", + ["en"]="smallbodyfont", + ["fr"]="policedecorpspetite", + ["it"]="piccolofontdelcorpo", + ["nl"]="kleinkorps", + ["pe"]="قلم‌بدنه‌کوچک", + ["ro"]="smallbodyfont", }, - ["three"]={ - ["cs"]="tri", - ["de"]="drei", - ["en"]="three", - ["fr"]="trois", - ["it"]="tre", - ["nl"]="drie", - ["pe"]="سه", - ["ro"]="trei", + ["smallbold"]={ + ["cs"]="maletucne", + ["de"]="kleinfett", + ["en"]="smallbold", + ["fr"]="petitgras", + ["it"]="piccolograssetto", + ["nl"]="kleinvet", + ["pe"]="مشکی‌کوچک", + ["ro"]="micaldin", }, - ["thursday"]={ - ["cs"]="ctvrtek", - ["de"]="donnerstag", - ["en"]="thursday", - ["fr"]="jeudi", - ["it"]="giovedi", - ["nl"]="donderdag", - ["pe"]="پنج‌شنبه", - ["ro"]="joi", + ["smallbolditalic"]={ + ["cs"]="maletucnekurzivni", + ["de"]="kleinfettitalic", + ["en"]="smallbolditalic", + ["fr"]="petitgrasitalique", + ["it"]="piccolograssettocorsivo", + ["nl"]="kleinvetitalic", + ["pe"]="ایتالیک‌مشکی‌کوچک", + ["ro"]="micaldininclinat", }, - ["tight"]={ - ["en"]="tight", - ["nl"]="krap", + ["smallboldslanted"]={ + ["cs"]="maletucnesklonene", + ["de"]="kleinfettgeneigt", + ["en"]="smallboldslanted", + ["fr"]="petitgrasincline", + ["it"]="piccolograssettoinclinato", + ["nl"]="kleinvetschuin", + ["pe"]="خوابیده‌مشکی‌کوچک", + ["ro"]="micaldininclinat", }, - ["title"]={ - ["cs"]="titul", - ["de"]="titel", - ["en"]="title", - ["fr"]="titre", - ["it"]="titolo", - ["nl"]="titel", - ["pe"]="عنوان", - ["ro"]="titlu", + ["smallcaps"]={ + ["cs"]="kapitalky", + ["de"]="smallcaps", + ["en"]="smallcaps", + ["fr"]="petitescaps", + ["it"]="maiuscoletto", + ["nl"]="smallcaps", + ["pe"]="smallcaps", + ["ro"]="majusculemici", }, - ["toggle"]={ - ["cs"]="toggle", - ["de"]="toggle", - ["en"]="wissel", - ["fr"]="toggle", - ["it"]="toggle", - ["nl"]="toggle", - ["pe"]="تغییر", - ["ro"]="toggle", + ["smaller"]={ + ["en"]="smaller", + ["fr"]="pluspetit", + ["nl"]="kleiner", }, - ["tolerant"]={ - ["cs"]="tolerantni", - ["de"]="tolerant", - ["en"]="tolerant", - ["fr"]="tolerant", - ["it"]="tollerante", - ["nl"]="soepel", - ["pe"]="بردبار", - ["ro"]="tolerant", + ["smallitalic"]={ + ["cs"]="malekurzivni", + ["de"]="kleinitalic", + ["en"]="smallitalic", + ["fr"]="petititalique", + ["it"]="piccolocorsivo", + ["nl"]="kleinitalic", + ["pe"]="ایتالیک‌کوچک", + ["ro"]="micitalic", }, - ["top"]={ - ["cs"]="vrsek", - ["de"]="oben", - ["en"]="top", - ["fr"]="sup", - ["it"]="cima", - ["nl"]="boven", - ["pe"]="بالا", - ["ro"]="sus", + ["smallitalicbold"]={ + ["cs"]="malekurzivnitucne", + ["de"]="kleinitalicfett", + ["en"]="smallitalicbold", + ["fr"]="petititaliquegras", + ["it"]="piccolocorsivograssetto", + ["nl"]="kleinitalicvet", + ["pe"]="مشکی‌ایتالیک‌کوچک", + ["ro"]="micitalicaldin", }, - ["tuesday"]={ - ["cs"]="utery", - ["de"]="dienstag", - ["en"]="tuesday", - ["fr"]="mardi", - ["it"]="martedi", - ["nl"]="dinsdag", - ["pe"]="سه‌شنبه", - ["ro"]="marti", + ["smallnormal"]={ + ["cs"]="malenormalni", + ["de"]="kleinnormal", + ["en"]="smallnormal", + ["fr"]="petitnormal", + ["it"]="piccolonormale", + ["nl"]="kleinnormaal", + ["pe"]="نرمال‌کوچک", + ["ro"]="micnormal", + }, + ["smallslanted"]={ + ["cs"]="malesklonene", + ["de"]="kleingeneigt", + ["en"]="smallslanted", + ["fr"]="petitincline", + ["it"]="piccoloinclinato", + ["nl"]="kleinschuin", + ["pe"]="خوابیده‌کوچک", + ["ro"]="micinclinat", + }, + ["smallslantedbold"]={ + ["cs"]="malesklonenetucne", + ["de"]="kleingeneigtfett", + ["en"]="smallslantedbold", + ["fr"]="petitinclinegras", + ["it"]="piccoloinclinatograssetto", + ["nl"]="kleinschuinvet", + ["pe"]="مشکی‌خوابیده‌کوچک", + ["ro"]="micinclinataldin", }, - ["two"]={ - ["cs"]="dve", - ["de"]="zwei", - ["en"]="two", - ["fr"]="deux", - ["it"]="due", - ["nl"]="twee", - ["pe"]="دو", - ["ro"]="doi", + ["smalltype"]={ + ["cs"]="maletype", + ["de"]="kleintippen", + ["en"]="smalltype", + ["fr"]="petitcaractere", + ["it"]="piccolotype", + ["nl"]="kleintype", + ["pe"]="تایپ‌کوچک", + ["ro"]="mictype", }, - ["txt"]={ - ["cs"]="txt", - ["de"]="txt", - ["en"]="txt", - ["fr"]="txt", - ["it"]="txt", - ["nl"]="txt", - ["pe"]="txt", - ["ro"]="txt", + ["somewhere"]={ + ["cs"]="nekde", + ["de"]="irgendwo", + ["en"]="somewhere", + ["fr"]="qqpart", + ["it"]="daqualcheparte", + ["nl"]="ergens", + ["pe"]="جایی", + ["ro"]="undeva", }, - ["type"]={ - ["cs"]="opis", - ["de"]="tippen", - ["en"]="type", - ["fr"]="type", - ["it"]="type", - ["nl"]="type", - ["pe"]="تایپ", - ["ro"]="type", + ["sorted"]={ + ["cs"]="tridene", + ["de"]="sortiert", + ["en"]="sorted", + ["fr"]="trie", + ["it"]="ordinato", + ["nl"]="gesorteerd", + ["pe"]="مرتب", + ["ro"]="sortat", }, - ["typing"]={ - ["cs"]="typing", - ["de"]="tippen", - ["en"]="typing", - ["fr"]="typing", - ["it"]="typing", - ["nl"]="typen", - ["pe"]="تایپ‌کردن", - ["ro"]="typing", + ["sorting"]={ + ["en"]="sorting", + ["fr"]="tri", }, - ["unavailable"]={ - ["cs"]="nedostupne", - ["de"]="nichtverfuegbar", - ["en"]="unavailable", - ["fr"]="indisponible", - ["it"]="nondisponibile", - ["nl"]="nietbeschikbaar", - ["pe"]="غیرموجود", - ["ro"]="nedisponibil", + ["space"]={ + ["cs"]="mezera", + ["de"]="spatium", + ["en"]="space", + ["fr"]="espace", + ["it"]="spazio", + ["nl"]="spatie", + ["pe"]="فضا", + ["ro"]="spatiu", }, - ["underbar"]={ - ["cs"]="podtrzeno", - ["de"]="unterstrichen", - ["en"]="underbar", - ["fr"]="souslignetout", - ["it"]="sottolinea", - ["nl"]="onderstreep", - ["pe"]="میله‌زیر", - ["ro"]="sublinie", + ["spacing"]={ + ["cs"]="mezerovani", + ["de"]="spatiumausgleich", + ["en"]="spacing", + ["fr"]="espacement", + ["it"]="spaziatura", + ["nl"]="spatiering", + ["pe"]="فضاگذاری", + ["ro"]="spatiere", }, - ["underbars"]={ - ["cs"]="podtrzeni", - ["de"]="unterstreichen", - ["en"]="underbars", - ["fr"]="sousligne", - ["it"]="sottolinee", - ["nl"]="onderstrepen", - ["pe"]="میله‌‌های‌زیر", - ["ro"]="sublinii", + ["speech"]={ + ["cs"]="speech", + ["de"]="speech", + ["en"]="speech", + ["fr"]="discours", + ["it"]="speech", + ["nl"]="spraak", + ["pe"]="سخنرانی", + ["ro"]="speech", }, - ["understrike"]={ - ["en"]="understrike", + ["split"]={ + ["cs"]="split", + ["de"]="split", + ["en"]="split", + ["fr"]="partager", + ["it"]="separa", + ["nl"]="splitsen", + ["pe"]="شکافتن", + ["ro"]="split", }, - ["understrikes"]={ - ["en"]="understrikes", + ["spot"]={ + ["cs"]="spot", + ["de"]="spot", + ["en"]="spot", + ["fr"]="tondirect", + ["it"]="spot", + ["nl"]="spot", + ["pe"]="لکه", + ["ro"]="spot", }, - ["unframed"]={ - ["en"]="unframed", + ["standard"]={ + ["cs"]="standardni", + ["de"]="standard", + ["en"]="standard", + ["fr"]="standard", + ["it"]="standard", + ["nl"]="standaard", + ["pe"]="استاندارد", + ["ro"]="standard", }, - ["unicode"]={ - ["en"]="unicode", + ["start"]={ + ["cs"]="start", + ["de"]="start", + ["en"]="start", + ["fr"]="activé", + ["it"]="inizia", + ["nl"]="start", + ["pe"]="شروع", + ["ro"]="start", }, - ["unit"]={ - ["cs"]="jednotka", - ["de"]="einheit", - ["en"]="unit", - ["fr"]="unite", - ["it"]="unita", - ["nl"]="eenheid", - ["pe"]="واحد", - ["ro"]="unitate", + ["starter"]={ + ["en"]="starter", + ["fr"]="demarreur", + ["nl"]="opener", }, - ["units"]={ - ["cs"]="jednotky", - ["de"]="einheiten", - ["en"]="units", - ["fr"]="unites", - ["it"]="unita", - ["nl"]="eenheden", - ["pe"]="واحدها", - ["ro"]="unitati", + ["sticker"]={ + ["cs"]="sticker", + ["de"]="sticker", + ["en"]="sticker", + ["fr"]="autocollant", + ["it"]="sticker", + ["nl"]="sticker", + ["pe"]="دشنه", + ["ro"]="sticker", }, - ["unknown"]={ - ["cs"]="neznamy", - ["de"]="unbekannt", - ["en"]="unknown", - ["fr"]="inconnu", - ["it"]="ignoto", - ["nl"]="onbekend", - ["pe"]="ناشناس", - ["ro"]="necunoscut", + ["stop"]={ + ["cs"]="stop", + ["de"]="stop", + ["en"]="stop", + ["fr"]="fin", + ["it"]="termina", + ["nl"]="stop", + ["pe"]="پایان", + ["ro"]="stop", }, - ["unpacked"]={ - ["cs"]="rozbalene", - ["de"]="ungepackt", - ["en"]="unpacked", - ["fr"]="degroupe", - ["it"]="unpacked", - ["nl"]="vanelkaar", - ["pe"]="غیرفشرده", - ["ro"]="despachetat", + ["stopper"]={ + ["cs"]="predel", + ["de"]="trenner", + ["en"]="stopper", + ["fr"]="stoppeur", + ["it"]="stopper", + ["nl"]="afsluiter", + ["pe"]="ایست", + ["ro"]="stopper", }, - ["up"]={ - ["en"]="up", - ["nl"]="omhoog", + ["stretch"]={ + ["cs"]="natahnout", + ["de"]="strecken", + ["en"]="stretch", + ["fr"]="etirer", + ["it"]="dilata", + ["nl"]="rek", + ["pe"]="بکش", + ["ro"]="dilatat", }, - ["url"]={ - ["cs"]="url", - ["de"]="url", - ["en"]="url", - ["fr"]="url", - ["it"]="url", - ["nl"]="url", - ["pe"]="url", - ["ro"]="url", + ["stretched"]={ + ["en"]="stretched", + ["fr"]="etire", }, - ["used"]={ - ["cs"]="uzito", - ["de"]="verwende", - ["en"]="used", - ["fr"]="used", - ["it"]="usato", - ["nl"]="gebruikt", - ["pe"]="استفاده‌شده", - ["ro"]="folosit", + ["strict"]={ + ["cs"]="striktni", + ["de"]="streng", + ["en"]="strict", + ["fr"]="strict", + ["it"]="rigido", + ["nl"]="streng", + ["pe"]="اکید", + ["ro"]="strict", }, - ["value"]={ - ["cs"]="hodnota", - ["de"]="wert", - ["en"]="value", - ["fr"]="valeur", - ["it"]="valore", - ["nl"]="waarde", - ["pe"]="مقدار", - ["ro"]="valoare", + ["strong"]={ + ["cs"]="strong", + ["de"]="strong", + ["en"]="strong", + ["fr"]="fort", + ["it"]="strong", + ["nl"]="sterk", + ["pe"]="محکم", + ["ro"]="strong", }, - ["vertical"]={ - ["cs"]="vertikalne", - ["de"]="vertikal", - ["en"]="vertical", - ["fr"]="verticale", - ["it"]="verticale", - ["nl"]="vertikaal", - ["pe"]="عمودی", - ["ro"]="vertical", + ["strut"]={ + ["cs"]="strut", + ["de"]="strut", + ["en"]="strut", + ["fr"]="entretoise", + ["it"]="strut", + ["nl"]="strut", + ["pe"]="بست", + ["ro"]="strut", }, - ["very"]={ - ["cs"]="velmi", - ["de"]="sehr", - ["en"]="very", - ["fr"]="tres", - ["it"]="molto", - ["nl"]="zeer", - ["pe"]="خیلی", - ["ro"]="foarte", + ["sub"]={ + ["cs"]="pod", + ["de"]="unter", + ["en"]="sub", + ["fr"]="sous", + ["it"]="sotto", + ["nl"]="sub", + ["pe"]="زیر", + ["ro"]="sub", }, - ["verystrict"]={ - ["cs"]="velmistriktni", - ["de"]="sehrstreng", - ["en"]="verystrict", - ["fr"]="tresstrict", - ["it"]="moltorigido", - ["nl"]="zeerstreng", - ["pe"]="خیلی‌سختگیر", - ["ro"]="foartestrict", + ["subbackward"]={ + ["cs"]="podzpet", + ["de"]="unterrueckwaerts", + ["en"]="subbackward", + ["fr"]="petitenarriere", + ["it"]="sottoindietro", + ["nl"]="subachteruit", + ["pe"]="زیرعقب‌گرد", + ["ro"]="subinapoi", }, - ["verytolerant"]={ - ["cs"]="velmitolerantni", - ["de"]="sehrtolerant", - ["en"]="verytolerant", - ["fr"]="trestolerant", - ["it"]="moltotollerante", - ["nl"]="zeersoepel", - ["pe"]="خیلی‌بردبار", - ["ro"]="foartetolerant", + ["subformula"]={ + ["cs"]="subrovnice", + ["de"]="subformel", + ["en"]="subformula", + ["fr"]="sousformule", + ["it"]="subformula", + ["nl"]="subformule", + ["pe"]="زیرفرمول", + ["ro"]="subformula", }, - ["vfenced"]={ - ["en"]="vfenced", + ["subforward"]={ + ["cs"]="podvpred", + ["de"]="untervorwaerts", + ["en"]="subforward", + ["fr"]="petitenavant", + ["it"]="sottoavanti", + ["nl"]="subvooruit", + ["pe"]="زیرجلوگرد", + ["ro"]="subavans", }, - ["vulgarfraction"]={ - ["en"]="vulgarfraction", + ["subject"]={ + ["cs"]="tema", + ["de"]="thema", + ["en"]="subject", + ["fr"]="sujet", + ["it"]="argomento", + ["nl"]="onderwerp", + ["pe"]="موضوع", + ["ro"]="subiect", }, - ["weak"]={ - ["cs"]="weak", - ["de"]="weak", - ["en"]="weak", - ["fr"]="weak", - ["it"]="weak", - ["nl"]="zwak", - ["pe"]="هفته", - ["ro"]="weak", + ["subpage"]={ + ["cs"]="podstranka", + ["de"]="unterseite", + ["en"]="subpage", + ["fr"]="souspage", + ["it"]="sottopagina", + ["nl"]="subpagina", + ["pe"]="زیرصفحه", + ["ro"]="subpagina", }, - ["wednesday"]={ - ["cs"]="streda", - ["de"]="mittwoch", - ["en"]="wednesday", - ["fr"]="mercredi", - ["it"]="mercoledi", - ["nl"]="woensdag", - ["pe"]="چهارشنبه", - ["ro"]="miercuri", + ["subs"]={ + ["en"]="subs", + ["fr"]="subs", }, - ["week"]={ - ["cs"]="tyden", - ["de"]="woche", - ["en"]="week", - ["fr"]="semaine", - ["it"]="settimana", - ["nl"]="week", - ["pe"]="هفته", - ["ro"]="saptamana", + ["subsection"]={ + ["cs"]="podsekce", + ["de"]="unterabsatz", + ["en"]="subsection", + ["fr"]="soussection", + ["it"]="sottocapoverso", + ["nl"]="subparagraaf", + ["pe"]="زیربخش", + ["ro"]="subsectiune", }, - ["weekday"]={ - ["cs"]="vsedniden", - ["de"]="wochentag", - ["en"]="weekday", - ["fr"]="joursemaine", - ["it"]="giornosettimana", - ["nl"]="weekdag", - ["pe"]="روزهفته", - ["ro"]="zisaptamana", + ["subsubject"]={ + ["cs"]="podtema", + ["de"]="unterthema", + ["en"]="subsubject", + ["fr"]="soussujet", + ["it"]="sottoargomento", + ["nl"]="subonderwerp", + ["pe"]="زیرموضوع", + ["ro"]="subsubiect", }, - ["white"]={ - ["cs"]="bily", - ["de"]="weiss", - ["en"]="white", - ["fr"]="blanc", - ["it"]="bianco", - ["nl"]="wit", - ["pe"]="سفید", - ["ro"]="alb", + ["subsubsection"]={ + ["cs"]="podpodsekce", + ["de"]="unterunterabsatz", + ["en"]="subsubsection", + ["fr"]="soussoussection", + ["it"]="sottosottocapoverso", + ["nl"]="subsubparagraaf", + ["pe"]="زیرزیربخش", + ["ro"]="subsubsectiune", }, - ["wide"]={ - ["cs"]="siroce", - ["de"]="breit", - ["en"]="wide", - ["fr"]="ample", - ["it"]="ampio", - ["nl"]="breed", - ["pe"]="گسترده", - ["ro"]="larg", + ["subsubsubject"]={ + ["cs"]="podpodtema", + ["de"]="unterunterthema", + ["en"]="subsubsubject", + ["fr"]="soussoussujet", + ["it"]="sottosottoargomento", + ["nl"]="subsubonderwerp", + ["pe"]="زیرزیرموضوع", + ["ro"]="subsubsubiect", }, - ["width"]={ - ["cs"]="sirka", - ["de"]="breite", - ["en"]="width", - ["fr"]="largeur", - ["it"]="ampiezza", - ["nl"]="breedte", - ["pe"]="عرض", - ["ro"]="latime", + ["subsubsubsection"]={ + ["cs"]="podpodpodsekce", + ["de"]="unterunterunterabsatz", + ["en"]="subsubsubsection", + ["fr"]="soussoussoussection", + ["it"]="sottosottosottocapoverso", + ["nl"]="subsubsubparagraaf", + ["pe"]="زیرزیرزیربخش", + ["ro"]="subsubsubsectiune", }, - ["word"]={ - ["cs"]="slovo", - ["de"]="wort", - ["en"]="word", - ["fr"]="mot", - ["it"]="parola", - ["nl"]="woord", - ["pe"]="word", - ["ro"]="cuvant", + ["subsubsubsubject"]={ + ["cs"]="podpodpodtema", + ["de"]="unterunterunterthema", + ["en"]="subsubsubsubject", + ["fr"]="soussoussoussujet", + ["it"]="sottosottosottoargomento", + ["nl"]="subsubsubonderwerp", + ["pe"]="زیرزیرزیرموضوع", + ["ro"]="subsubsubsubiect", }, - ["words"]={ - ["en"]="words", + ["subsubsubsubsection"]={ + ["cs"]="podpodpodpodsekce", + ["de"]="unterunterunterunterabsatz", + ["en"]="subsubsubsubsection", + ["fr"]="soussoussoussoussection", + ["it"]="sottosottosottosottocapoverso", + ["nl"]="subsubsubsubparagraaf", + ["pe"]="زیرزیرزیرزیربخش", + ["ro"]="subsubsubsubsectiune", }, - ["xml"]={ - ["cs"]="xml", - ["de"]="xml", - ["en"]="xml", - ["fr"]="xml", - ["it"]="xml", - ["nl"]="xml", - ["pe"]="xml", - ["ro"]="xml", + ["subsubsubsubsubject"]={ + ["cs"]="podpodpodpodtema", + ["de"]="unterunterunterunterthema", + ["en"]="subsubsubsubsubject", + ["fr"]="soussoussoussoussujet", + ["it"]="sottosottosottosottoargomento", + ["nl"]="subsubsubsubonderwerp", + ["pe"]="زیرزیرزیرزیرموضوع", + ["ro"]="subsubsubsubsubiect", }, - ["year"]={ - ["cs"]="rok", - ["de"]="jahr", - ["en"]="year", - ["fr"]="annee", - ["it"]="anno", - ["nl"]="jaar", - ["pe"]="سال", - ["ro"]="an", + ["subsubsubsubsubsection"]={ + ["cs"]="podpodpodpodpodsekce", + ["de"]="unterunterunterunterunterabsatz", + ["en"]="subsubsubsubsubsection", + ["fr"]="soussoussoussoussoussection", + ["it"]="sottosottosottosottosottocapoverso", + ["nl"]="subsubsubsubsubparagraaf", + ["pe"]="زیرزیرزیرزیرزیربخش", + ["ro"]="subsubsubsubsubsectiune", }, - ["yes"]={ - ["cs"]="ano", - ["de"]="ja", - ["en"]="yes", - ["fr"]="oui", - ["it"]="si", - ["nl"]="ja", - ["pe"]="بله", - ["ro"]="da", + ["subsubsubsubsubsubject"]={ + ["cs"]="podpodpodpodpodtema", + ["de"]="unterunterunterunterunterthema", + ["en"]="subsubsubsubsubsubject", + ["fr"]="soussoussoussoussoussujet", + ["it"]="sottosottosottosottosottoargomento", + ["nl"]="subsubsubsubsubonderwerp", + ["pe"]="زیرزیرزیرزیرزیرموضوع", + ["ro"]="subsubsubsubsubsubiect", }, - }, - ["setupstrings"]={ - ["cd:buffer"]={ - ["cs"]="buffer", - ["de"]="buffer", - ["en"]="buffer", - ["fr"]="buffer", - ["it"]="buffer", - ["nl"]="buffer", - ["ro"]="buffer", + ["subsubsubsubsubsubsection"]={ + ["cs"]="podpodpodpodpodpodsekce", + ["de"]="unterunterunterunterunterunterabsatz", + ["en"]="subsubsubsubsubsubsection", + ["fr"]="soussoussoussoussoussoussection", + ["it"]="sottosottosottosottosottosottocapoverso", + ["nl"]="subsubsubsubsubsubparagraaf", + ["pe"]="زیرزیرزیرزیرزیرزیربخش", + ["ro"]="subsubsubsubsubsubsectiune", }, - ["cd:category"]={ - ["cs"]="category", - ["de"]="category", - ["en"]="category", - ["fr"]="category", - ["it"]="category", - ["nl"]="category", - ["ro"]="category", + ["subsubsubsubsubsubsubject"]={ + ["cs"]="podpodpodpodpodpodtema", + ["de"]="unterunterunterunterunterunterthema", + ["en"]="subsubsubsubsubsubsubject", + ["fr"]="soussoussoussoussoussoussujet", + ["it"]="sottosottosottosottosottosottoargomento", + ["nl"]="subsubsubsubsubsubonderwerp", + ["pe"]="زیرزیرزیرزیرزیرزیرموضوع", + ["ro"]="subsubsubsubsubsubsubiect", }, - ["cd:character"]={ - ["cs"]="character", - ["de"]="character", - ["en"]="character", - ["fr"]="character", - ["it"]="character", - ["nl"]="karakter", - ["ro"]="character", + ["subsubsubsubsubsubsubsection"]={ + ["cs"]="podpodpodpodpodpodpodsekce", + ["de"]="unterunterunterunterunterunterunterabsatz", + ["en"]="subsubsubsubsubsubsubsection", + ["fr"]="soussoussoussoussoussoussoussection", + ["it"]="sottosottosottosottosottosottosottocapoverso", + ["nl"]="subsubsubsubsubsubsubparagraaf", + ["pe"]="زیرزیرزیرزیرزیرزیرزیربخش", + ["ro"]="subsubsubsubsubsubsubsectiune", }, - ["cd:color"]={ - ["cs"]="color", - ["de"]="color", - ["en"]="color", - ["fr"]="color", - ["it"]="color", - ["nl"]="kleur", - ["ro"]="color", + ["subsubsubsubsubsubsubsubject"]={ + ["cs"]="podpodpodpodpodpodpodtema", + ["de"]="unterunterunterunterunterunterunterthema", + ["en"]="subsubsubsubsubsubsubsubject", + ["fr"]="soussoussoussoussoussoussoussujet", + ["it"]="sottosottosottosottosottosottosottoargomento", + ["nl"]="subsubsubsubsubsubsubonderwerp", + ["pe"]="زیرزیرزیرزیرزیرزیرزیرموضوع", + ["ro"]="subsubsubsubsubsubsubsubiect", }, - ["cd:column"]={ - ["cs"]="column", - ["de"]="column", - ["en"]="column", - ["fr"]="column", - ["it"]="column", - ["nl"]="kolom", - ["ro"]="column", + ["subsubsubsubsubsubsubsubsection"]={ + ["cs"]="podpodpodpodpodpodpodpodsekce", + ["de"]="unterunterunterunterunterunterunterunterabsatz", + ["en"]="subsubsubsubsubsubsubsubsection", + ["fr"]="soussoussoussoussoussoussoussoussection", + ["it"]="sottosottosottosottosottosottosottosottocapoverso", + ["nl"]="subsubsubsubsubsubsubsubparagraaf", + ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیربخش", + ["ro"]="subsubsubsubsubsubsubsubsectiune", }, - ["cd:command"]={ - ["cs"]="Befehl", - ["de"]="Befehl", - ["en"]="command", - ["fr"]="Befehl", - ["it"]="Befehl", - ["nl"]="commando", - ["ro"]="Befehl", + ["subsubsubsubsubsubsubsubsubject"]={ + ["cs"]="podpodpodpodpodpodpodpodtema", + ["de"]="unterunterunterunterunterunterunterunterthema", + ["en"]="subsubsubsubsubsubsubsubsubject", + ["fr"]="soussoussoussoussoussoussoussoussujet", + ["it"]="sottosottosottosottosottosottosottosottoargomento", + ["nl"]="subsubsubsubsubsubsubsubonderwerp", + ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیرموضوع", + ["ro"]="subsubsubsubsubsubsubsubsubiect", }, - ["cd:content"]={ - ["cs"]="content", - ["de"]="content", - ["en"]="content", - ["fr"]="content", - ["it"]="content", - ["nl"]="inhoud", - ["ro"]="content", + ["subsubsubsubsubsubsubsubsubsection"]={ + ["cs"]="podpodpodpodpodpodpodpodpodsekce", + ["de"]="unterunterunterunterunterunterunterunterunterabsatz", + ["en"]="subsubsubsubsubsubsubsubsubsection", + ["fr"]="soussoussoussoussoussoussoussoussoussection", + ["it"]="sottosottosottosottosottosottosottosottosottocapoverso", + ["nl"]="subsubsubsubsubsubsubsubsubparagraaf", + ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیرزیربخش", + ["ro"]="subsubsubsubsubsubsubsubsubsectiune", }, - ["cd:csname"]={ - ["cs"]="csname", - ["de"]="csname", - ["en"]="csname", - ["fr"]="csname", - ["it"]="csname", - ["nl"]="naam", - ["ro"]="csname", + ["subsubsubsubsubsubsubsubsubsubject"]={ + ["cs"]="podpodpodpodpodpodpodpodpodtema", + ["de"]="unterunterunterunterunterunterunterunterunterthema", + ["en"]="subsubsubsubsubsubsubsubsubsubject", + ["fr"]="soussoussoussoussoussoussoussoussoussujet", + ["it"]="sottosottosottosottosottosottosottosottosottoargomento", + ["nl"]="subsubsubsubsubsubsubsubsubonderwerp", + ["pe"]="زیرزیرزیرزیرزیرزیرزیرزیرزیرموضوع", + ["ro"]="subsubsubsubsubsubsubsubsubsubiect", }, - ["cd:delimiter"]={ - ["cs"]="delimiter", - ["de"]="delimiter", - ["en"]="delimiter", - ["fr"]="delimiter", - ["it"]="delimiter", - ["nl"]="delimiter", - ["ro"]="delimiter", + ["sunday"]={ + ["cs"]="nedele", + ["de"]="sonntag", + ["en"]="sunday", + ["fr"]="dimanche", + ["it"]="domenica", + ["nl"]="zondag", + ["pe"]="یک‌شنبه", + ["ro"]="duminica", }, - ["cd:destination"]={ - ["cs"]="destination", - ["de"]="destination", - ["en"]="destination", - ["fr"]="destination", - ["it"]="destination", - ["nl"]="bestemming", - ["ro"]="destination", + ["support"]={ + ["cs"]="podpora", + ["de"]="support", + ["en"]="support", + ["fr"]="support", + ["it"]="supporto", + ["nl"]="support", + ["pe"]="حمایت", + ["ro"]="suport", }, - ["cd:dimension"]={ - ["cs"]="Dimension", - ["de"]="Dimension", - ["en"]="dimension", - ["fr"]="Dimension", - ["it"]="Dimension", - ["nl"]="maat", - ["ro"]="Dimension", + ["sym"]={ + ["cs"]="sym", + ["de"]="sym", + ["en"]="sym", + ["fr"]="sym", + ["it"]="sim", + ["nl"]="sym", + ["pe"]="نم", + ["ro"]="sym", }, - ["cd:displaymath"]={ - ["cs"]="formula", - ["de"]="formula", - ["en"]="formula", - ["fr"]="formula", - ["it"]="formula", - ["nl"]="formule", - ["ro"]="formula", + ["symbol"]={ + ["cs"]="symbol", + ["de"]="symbol", + ["en"]="symbol", + ["fr"]="symbole", + ["it"]="simbolo", + ["nl"]="symbool", + ["pe"]="نماد", + ["ro"]="simbol", }, - ["cd:false"]={ - ["cs"]="false", - ["de"]="false", - ["en"]="false", - ["fr"]="false", - ["it"]="false", - ["nl"]="false", - ["ro"]="false", + ["synchronize"]={ + ["cs"]="synchronize", + ["de"]="synchronize", + ["en"]="synchronize", + ["fr"]="synchroniser", + ["it"]="synchronize", + ["nl"]="synchroniseer", + ["pe"]="تطابق", + ["ro"]="synchronize", }, - ["cd:file"]={ - ["cs"]="file", - ["de"]="file", - ["en"]="file", - ["fr"]="file", - ["it"]="file", - ["nl"]="file", - ["ro"]="file", + ["synonym"]={ + ["en"]="synonym", + ["fr"]="synonyme", }, - ["cd:path"]={ - ["cs"]="path", - ["de"]="path", - ["en"]="path", - ["fr"]="path", - ["it"]="path", - ["nl"]="path", - ["ro"]="path", + ["system"]={ + ["cs"]="system", + ["de"]="systeme", + ["en"]="system", + ["fr"]="systeme", + ["it"]="sistema", + ["nl"]="systeem", + ["pe"]="سیستم", + ["ro"]="sistem", }, - ["cd:first"]={ - ["cs"]="first", - ["de"]="first", - ["en"]="first", - ["fr"]="first", - ["it"]="first", - ["nl"]="eerste", - ["ro"]="first", + ["table"]={ + ["cs"]="tabulka", + ["de"]="tabelle", + ["en"]="table", + ["fr"]="table", + ["it"]="tabella", + ["nl"]="tabel", + ["pe"]="جدول", + ["ro"]="tabelul", }, - ["cd:font"]={ - ["cs"]="font", - ["de"]="font", - ["en"]="font", - ["fr"]="font", - ["it"]="font", - ["nl"]="font", - ["ro"]="font", + ["tablehead"]={ + ["cs"]="zahlavitabulky", + ["de"]="tabellenueberschrift", + ["en"]="tablehead", + ["fr"]="tetetableau", + ["it"]="testatabella", + ["nl"]="tabelkop", + ["pe"]="سرجدول", + ["ro"]="antettabel", }, - ["cd:formula"]={ - ["cs"]="Formel", - ["de"]="Formel", - ["en"]="formula", - ["fr"]="Formel", - ["it"]="Formel", - ["nl"]="formule", - ["ro"]="Formel", + ["tables"]={ + ["cs"]="tabulky", + ["de"]="tabellen", + ["en"]="tables", + ["fr"]="tables", + ["it"]="tabelle", + ["nl"]="tabellen", + ["pe"]="جدولها", + ["ro"]="tabelele", }, - ["cd:identifier"]={ - ["cs"]="Name", - ["de"]="Name", - ["en"]="identifier", - ["fr"]="Name", - ["it"]="Name", - ["nl"]="naam", - ["ro"]="Name", + ["tabletail"]={ + ["cs"]="konectabulky", + ["de"]="tabellenende", + ["en"]="tabletail", + ["fr"]="queuetable", + ["it"]="codatabella", + ["nl"]="tabelstaart", + ["pe"]="دنباله‌جدول", + ["ro"]="subsoltabel", }, - ["cd:index"]={ - ["cs"]="entry", - ["de"]="entry", - ["en"]="entry", - ["fr"]="entry", - ["it"]="entry", - ["nl"]="ingang", - ["ro"]="entry", + ["tabulate"]={ + ["cs"]="tabelator", + ["de"]="tabulator", + ["en"]="tabulate", + ["fr"]="tabulation", + ["it"]="tabulato", + ["nl"]="tabulatie", + ["pe"]="جدول‌بندی", + ["ro"]="tabulate", }, - ["cd:inherits"]={ - ["cs"]="inherits", - ["de"]="inherits", - ["en"]="inherits", - ["fr"]="inherits", - ["it"]="inherits", - ["nl"]="erft", - ["ro"]="inherits", + ["tabulatehead"]={ + ["cs"]="tabulatehead", + ["de"]="tabulatehead", + ["en"]="tabulatehead", + ["fr"]="tetetabulation", + ["it"]="testatabulato", + ["nl"]="tabulatiekop", + ["pe"]="سرجدول‌بندی", + ["ro"]="tabulatehead", }, - ["cd:key"]={ - ["cs"]="key", - ["de"]="key", - ["en"]="key", - ["fr"]="key", - ["it"]="key", - ["nl"]="parameter", - ["ro"]="key", + ["tabulatetail"]={ + ["cs"]="tabulatetail", + ["de"]="tabulatetail", + ["en"]="tabulatetail", + ["fr"]="queuetabulation", + ["it"]="codatabulato", + ["nl"]="tabulatiestaart", + ["pe"]="دنباله‌جدول‌بندی", + ["ro"]="tabulatetail", }, - ["cd:language"]={ - ["cs"]="sprache", - ["de"]="sprache", - ["en"]="language", - ["fr"]="sprache", - ["it"]="sprache", - ["nl"]="taal", - ["ro"]="sprache", + ["tall"]={ + ["cs"]="vysoko", + ["de"]="lang", + ["en"]="tall", + ["fr"]="grand", + ["it"]="alto", + ["nl"]="lang", + ["pe"]="دراز", + ["ro"]="inalt", }, - ["cd:last"]={ - ["cs"]="last", - ["de"]="last", - ["en"]="last", - ["fr"]="last", - ["it"]="last", - ["nl"]="laatste", - ["ro"]="last", + ["teletype"]={ + ["cs"]="strojopis", + ["de"]="fernschreiber", + ["en"]="teletype", + ["fr"]="caractereterminal", + ["it"]="teletype", + ["nl"]="teletype", + ["pe"]="دورنگاره", + ["ro"]="teletype", }, - ["cd:list"]={ - ["cs"]="Liste", - ["de"]="Liste", - ["en"]="list", - ["fr"]="Liste", - ["it"]="Liste", - ["nl"]="lijst", - ["ro"]="Liste", + ["temporary"]={ + ["cs"]="docasne", + ["de"]="temporaer", + ["en"]="temporary", + ["fr"]="temporaire", + ["it"]="temporaneo", + ["nl"]="voorlopig", + ["pe"]="موقتی", + ["ro"]="temporar", }, - ["cd:lpath"]={ - ["cs"]="lpath", - ["de"]="lpath", - ["en"]="lpath", - ["fr"]="lpath", - ["it"]="lpath", - ["nl"]="lpath", - ["ro"]="lpath", + ["test"]={ + ["cs"]="test", + ["de"]="test", + ["en"]="test", + ["fr"]="test", + ["it"]="test", + ["nl"]="test", + ["pe"]="تست", + ["ro"]="test", }, - ["cd:luafunction"]={ - ["cs"]="luafunction", - ["de"]="luafunction", - ["en"]="luafunction", - ["fr"]="luafunction", - ["it"]="luafunction", - ["nl"]="luafunction", - ["ro"]="luafunction", + ["text"]={ + ["cs"]="text", + ["de"]="text", + ["en"]="text", + ["fr"]="texte", + ["it"]="testo", + ["nl"]="tekst", + ["pe"]="متن", + ["ro"]="text", }, - ["cd:mark"]={ - ["cs"]="Beschriftung", - ["de"]="Beschriftung", - ["en"]="mark", - ["fr"]="Beschriftung", - ["it"]="Beschriftung", - ["nl"]="markering", - ["ro"]="Beschriftung", + ["textnote"]={ + ["en"]="textnote", + ["fr"]="notetexte", + ["nl"]="tekstnoot", }, - ["cd:marking"]={ - ["cs"]="marking", - ["de"]="marking", - ["en"]="marking", - ["fr"]="marking", - ["it"]="marking", - ["nl"]="markering", - ["ro"]="marking", + ["three"]={ + ["cs"]="tri", + ["de"]="drei", + ["en"]="three", + ["fr"]="trois", + ["it"]="tre", + ["nl"]="drie", + ["pe"]="سه", + ["ro"]="trei", }, - ["cd:math"]={ - ["cs"]="formula", - ["de"]="formula", - ["en"]="formula", - ["fr"]="formula", - ["it"]="formula", - ["nl"]="formule", - ["ro"]="formula", + ["thursday"]={ + ["cs"]="ctvrtek", + ["de"]="donnerstag", + ["en"]="thursday", + ["fr"]="jeudi", + ["it"]="giovedi", + ["nl"]="donderdag", + ["pe"]="پنج‌شنبه", + ["ro"]="joi", }, - ["cd:matrix"]={ - ["cs"]="n*m", - ["de"]="n*m", - ["en"]="n*m", - ["fr"]="n*m", - ["it"]="n*m", - ["nl"]="n*m", - ["ro"]="n*m", + ["tight"]={ + ["en"]="tight", + ["fr"]="resserre", + ["nl"]="krap", }, - ["cd:name"]={ - ["cs"]="Name", - ["de"]="Name", - ["en"]="name", - ["fr"]="Name", - ["it"]="Name", - ["nl"]="naam", - ["ro"]="Name", + ["title"]={ + ["cs"]="titul", + ["de"]="titel", + ["en"]="title", + ["fr"]="titre", + ["it"]="titolo", + ["nl"]="titel", + ["pe"]="عنوان", + ["ro"]="titlu", }, - ["cd:node"]={ - ["cs"]="node", - ["de"]="node", - ["en"]="node", - ["fr"]="node", - ["it"]="node", - ["nl"]="node", - ["ro"]="node", + ["toggle"]={ + ["cs"]="toggle", + ["de"]="toggle", + ["en"]="wissel", + ["fr"]="basculer", + ["it"]="toggle", + ["nl"]="toggle", + ["pe"]="تغییر", + ["ro"]="toggle", }, - ["cd:nothing"]={ - ["cs"]="empty", - ["de"]="empty", - ["en"]="empty", - ["fr"]="empty", - ["it"]="empty", - ["nl"]="leeg", - ["ro"]="empty", + ["tolerant"]={ + ["cs"]="tolerantni", + ["de"]="tolerant", + ["en"]="tolerant", + ["fr"]="tolerant", + ["it"]="tollerante", + ["nl"]="soepel", + ["pe"]="بردبار", + ["ro"]="tolerant", }, - ["cd:number"]={ - ["cs"]="Nummer", - ["de"]="Nummer", - ["en"]="number", - ["fr"]="Nummer", - ["it"]="Nummer", - ["nl"]="getal", - ["ro"]="Nummer", + ["top"]={ + ["cs"]="vrsek", + ["de"]="oben", + ["en"]="top", + ["fr"]="haut", + ["it"]="cima", + ["nl"]="boven", + ["pe"]="بالا", + ["ro"]="sus", }, - ["cd:optional"]={ - ["cs"]="opt", - ["de"]="opt", - ["en"]="opt", - ["fr"]="opt", - ["it"]="opt", - ["nl"]="opt", - ["ro"]="opt", + ["tuesday"]={ + ["cs"]="utery", + ["de"]="dienstag", + ["en"]="tuesday", + ["fr"]="mardi", + ["it"]="martedi", + ["nl"]="dinsdag", + ["pe"]="سه‌شنبه", + ["ro"]="marti", }, - ["cd:plural"]={ - ["cs"]="plural", - ["de"]="plural", - ["en"]="plural", - ["fr"]="plural", - ["it"]="plural", - ["nl"]="naam", - ["ro"]="plural", + ["two"]={ + ["cs"]="dve", + ["de"]="zwei", + ["en"]="two", + ["fr"]="deux", + ["it"]="due", + ["nl"]="twee", + ["pe"]="دو", + ["ro"]="doi", }, - ["cd:position"]={ - ["cs"]="position", - ["de"]="position", - ["en"]="position", - ["fr"]="position", - ["it"]="position", - ["nl"]="positie", - ["ro"]="position", + ["txt"]={ + ["cs"]="txt", + ["de"]="txt", + ["en"]="txt", + ["fr"]="txt", + ["it"]="txt", + ["nl"]="txt", + ["pe"]="txt", + ["ro"]="txt", }, - ["cd:processor"]={ - ["cs"]="processor", - ["de"]="processor", - ["en"]="processor", - ["fr"]="processor", - ["it"]="processor", - ["nl"]="verwerker", - ["ro"]="processor", + ["type"]={ + ["cs"]="opis", + ["de"]="tippen", + ["en"]="type", + ["fr"]="transcrire", + ["it"]="type", + ["nl"]="type", + ["pe"]="تایپ", + ["ro"]="type", }, - ["cd:reference"]={ - ["cs"]="reference", - ["de"]="reference", - ["en"]="reference", - ["fr"]="reference", - ["it"]="reference", - ["nl"]="verwijzing", - ["ro"]="reference", + ["typing"]={ + ["cs"]="typing", + ["de"]="tippen", + ["en"]="typing", + ["fr"]="transcription", + ["it"]="typing", + ["nl"]="typen", + ["pe"]="تایپ‌کردن", + ["ro"]="typing", }, - ["cd:row"]={ - ["cs"]="row", - ["de"]="row", - ["en"]="row", - ["fr"]="row", - ["it"]="row", - ["nl"]="rij", - ["ro"]="row", + ["unavailable"]={ + ["cs"]="nedostupne", + ["de"]="nichtverfuegbar", + ["en"]="unavailable", + ["fr"]="indisponible", + ["it"]="nondisponibile", + ["nl"]="nietbeschikbaar", + ["pe"]="غیرموجود", + ["ro"]="nedisponibil", }, - ["cd:section"]={ - ["cs"]="Abschnitt", - ["de"]="Abschnitt", - ["en"]="section", - ["fr"]="Abschnitt", - ["it"]="Abschnitt", - ["nl"]="sectie", - ["ro"]="Abschnitt", + ["underbar"]={ + ["cs"]="podtrzeno", + ["de"]="unterstrichen", + ["en"]="underbar", + ["fr"]="souligner", + ["it"]="sottolinea", + ["nl"]="onderstreep", + ["pe"]="میله‌زیر", + ["ro"]="sublinie", }, - ["cd:sectionblock"]={ - ["cs"]="sectionblock", - ["de"]="sectionblock", - ["en"]="sectionblock", - ["fr"]="sectionblock", - ["it"]="sectionblock", - ["nl"]="sectieblok", - ["ro"]="sectionblock", + ["underbars"]={ + ["cs"]="podtrzeni", + ["de"]="unterstreichen", + ["en"]="underbars", + ["fr"]="soulignermots", + ["it"]="sottolinee", + ["nl"]="onderstrepen", + ["pe"]="میله‌‌های‌زیر", + ["ro"]="sublinii", }, - ["cd:see"]={ - ["cs"]="siehe", - ["de"]="siehe", - ["en"]="see", - ["fr"]="siehe", - ["it"]="siehe", - ["nl"]="zie", - ["ro"]="siehe", + ["understrike"]={ + ["en"]="understrike", + ["fr"]="soubarrer", }, - ["cd:setup"]={ - ["cs"]="setup", - ["de"]="setup", - ["en"]="setup", - ["fr"]="setup", - ["it"]="setup", - ["nl"]="setup", - ["ro"]="setup", + ["understrikes"]={ + ["en"]="understrikes", + ["fr"]="soubarrermots", }, - ["cd:singular"]={ - ["cs"]="singular", - ["de"]="singular", - ["en"]="singular", - ["fr"]="singular", - ["it"]="singular", - ["nl"]="naam", - ["ro"]="singular", + ["unframed"]={ + ["en"]="unframed", + ["fr"]="desencadre", }, - ["cd:style"]={ - ["cs"]="style", - ["de"]="style", - ["en"]="style", - ["fr"]="style", - ["it"]="style", - ["nl"]="letter", - ["ro"]="style", + ["unicode"]={ + ["en"]="unicode", + ["fr"]="unicode", }, - ["cd:template"]={ - ["cs"]="template", - ["de"]="template", - ["en"]="template", - ["fr"]="template", - ["it"]="template", - ["nl"]="sjabloon", - ["ro"]="template", + ["unit"]={ + ["cs"]="jednotka", + ["de"]="einheit", + ["en"]="unit", + ["fr"]="unite", + ["it"]="unita", + ["nl"]="eenheid", + ["pe"]="واحد", + ["ro"]="unitate", }, - ["cd:text"]={ - ["cs"]="Text", - ["de"]="Text", - ["en"]="text", - ["fr"]="Text", - ["it"]="Text", - ["nl"]="tekst", - ["ro"]="Text", + ["units"]={ + ["cs"]="jednotky", + ["de"]="einheiten", + ["en"]="units", + ["fr"]="unites", + ["it"]="unita", + ["nl"]="eenheden", + ["pe"]="واحدها", + ["ro"]="unitati", }, - ["cd:title"]={ - ["cs"]="Setup", - ["de"]="Setup", - ["en"]="setup", - ["fr"]="Setup", - ["it"]="Setup", - ["nl"]="setup", - ["ro"]="Setup", + ["unknown"]={ + ["cs"]="neznamy", + ["de"]="unbekannt", + ["en"]="unknown", + ["fr"]="inconnu", + ["it"]="ignoto", + ["nl"]="onbekend", + ["pe"]="ناشناس", + ["ro"]="necunoscut", }, - ["cd:triplet"]={ - ["cs"]="triplet", - ["de"]="triplet", - ["en"]="triplet", - ["fr"]="triplet", - ["it"]="triplet", - ["nl"]="triplet", - ["ro"]="triplet", + ["unpacked"]={ + ["cs"]="rozbalene", + ["de"]="ungepackt", + ["en"]="unpacked", + ["fr"]="avecespaceentreitem", + ["it"]="unpacked", + ["nl"]="vanelkaar", + ["pe"]="غیرفشرده", + ["ro"]="despachetat", }, - ["cd:true"]={ - ["cs"]="true", - ["de"]="true", - ["en"]="true", - ["fr"]="true", - ["it"]="true", - ["nl"]="true", - ["ro"]="true", + ["up"]={ + ["en"]="up", + ["fr"]="enhaut", + ["nl"]="omhoog", }, - ["cd:url"]={ + ["url"]={ ["cs"]="url", ["de"]="url", ["en"]="url", ["fr"]="url", ["it"]="url", ["nl"]="url", + ["pe"]="url", ["ro"]="url", }, - ["cd:userdata"]={ - ["cs"]="userdata", - ["de"]="userdata", - ["en"]="userdata", - ["fr"]="userdata", - ["it"]="userdata", - ["nl"]="gebruikersdata", - ["ro"]="userdata", + ["used"]={ + ["cs"]="uzito", + ["de"]="verwende", + ["en"]="used", + ["fr"]="utilise", + ["it"]="usato", + ["nl"]="gebruikt", + ["pe"]="استفاده‌شده", + ["ro"]="folosit", }, - ["cd:value"]={ - ["cs"]="value", - ["de"]="value", + ["value"]={ + ["cs"]="hodnota", + ["de"]="wert", ["en"]="value", - ["fr"]="value", - ["it"]="value", + ["fr"]="valeur", + ["it"]="valore", ["nl"]="waarde", - ["ro"]="value", + ["pe"]="مقدار", + ["ro"]="valoare", }, - ["cd:word"]={ - ["cs"]="word", - ["de"]="word", + ["vertical"]={ + ["cs"]="vertikalne", + ["de"]="vertikal", + ["en"]="vertical", + ["fr"]="vertical", + ["it"]="verticale", + ["nl"]="vertikaal", + ["pe"]="عمودی", + ["ro"]="vertical", + }, + ["very"]={ + ["cs"]="velmi", + ["de"]="sehr", + ["en"]="very", + ["fr"]="tres", + ["it"]="molto", + ["nl"]="zeer", + ["pe"]="خیلی", + ["ro"]="foarte", + }, + ["verystrict"]={ + ["cs"]="velmistriktni", + ["de"]="sehrstreng", + ["en"]="verystrict", + ["fr"]="tresstrict", + ["it"]="moltorigido", + ["nl"]="zeerstreng", + ["pe"]="خیلی‌سختگیر", + ["ro"]="foartestrict", + }, + ["verytolerant"]={ + ["cs"]="velmitolerantni", + ["de"]="sehrtolerant", + ["en"]="verytolerant", + ["fr"]="trestolerant", + ["it"]="moltotollerante", + ["nl"]="zeersoepel", + ["pe"]="خیلی‌بردبار", + ["ro"]="foartetolerant", + }, + ["vfenced"]={ + ["en"]="vfenced", + ["fr"]="cloturev", + }, + ["vulgarfraction"]={ + ["en"]="vulgarfraction", + ["fr"]="vulgarfraction", + }, + ["weak"]={ + ["cs"]="weak", + ["de"]="weak", + ["en"]="weak", + ["fr"]="faible", + ["it"]="weak", + ["nl"]="zwak", + ["pe"]="هفته", + ["ro"]="weak", + }, + ["wednesday"]={ + ["cs"]="streda", + ["de"]="mittwoch", + ["en"]="wednesday", + ["fr"]="mercredi", + ["it"]="mercoledi", + ["nl"]="woensdag", + ["pe"]="چهارشنبه", + ["ro"]="miercuri", + }, + ["week"]={ + ["cs"]="tyden", + ["de"]="woche", + ["en"]="week", + ["fr"]="semaine", + ["it"]="settimana", + ["nl"]="week", + ["pe"]="هفته", + ["ro"]="saptamana", + }, + ["weekday"]={ + ["cs"]="vsedniden", + ["de"]="wochentag", + ["en"]="weekday", + ["fr"]="joursemaine", + ["it"]="giornosettimana", + ["nl"]="weekdag", + ["pe"]="روزهفته", + ["ro"]="zisaptamana", + }, + ["white"]={ + ["cs"]="bily", + ["de"]="weiss", + ["en"]="white", + ["fr"]="blanc", + ["it"]="bianco", + ["nl"]="wit", + ["pe"]="سفید", + ["ro"]="alb", + }, + ["wide"]={ + ["cs"]="siroce", + ["de"]="breit", + ["en"]="wide", + ["fr"]="ample", + ["it"]="ampio", + ["nl"]="breed", + ["pe"]="گسترده", + ["ro"]="larg", + }, + ["width"]={ + ["cs"]="sirka", + ["de"]="breite", + ["en"]="width", + ["fr"]="largeur", + ["it"]="ampiezza", + ["nl"]="breedte", + ["pe"]="عرض", + ["ro"]="latime", + }, + ["word"]={ + ["cs"]="slovo", + ["de"]="wort", ["en"]="word", - ["fr"]="word", - ["it"]="word", + ["fr"]="mot", + ["it"]="parola", ["nl"]="woord", - ["ro"]="word", + ["pe"]="word", + ["ro"]="cuvant", }, - ["cd:xmlsetup"]={ - ["cs"]="xmlsetup", - ["de"]="xmlsetup", - ["en"]="xmlsetup", - ["fr"]="xmlsetup", - ["it"]="xmlsetup", - ["nl"]="xmlsetup", - ["ro"]="xmlsetup", + ["words"]={ + ["en"]="words", + ["fr"]="mots", + }, + ["xml"]={ + ["cs"]="xml", + ["de"]="xml", + ["en"]="xml", + ["fr"]="xml", + ["it"]="xml", + ["nl"]="xml", + ["pe"]="xml", + ["ro"]="xml", + }, + ["year"]={ + ["cs"]="rok", + ["de"]="jahr", + ["en"]="year", + ["fr"]="annee", + ["it"]="anno", + ["nl"]="jaar", + ["pe"]="سال", + ["ro"]="an", + }, + ["yes"]={ + ["cs"]="ano", + ["de"]="ja", + ["en"]="yes", + ["fr"]="oui", + ["it"]="si", + ["nl"]="ja", + ["pe"]="بله", + ["ro"]="da", }, - ["cd:sign"] = { en = "[-+]" }, - ["cd:csname-s"] = { en = "\\..." }, - ["cd:csname-l"] = { en = "\\..." }, - ["cd:noargument-s"] = { en = "\\..." }, - ["cd:noargument-l"] = { en = "\\..." }, - ["cd:oneargument"] = { en = "\\...#1" }, - ["cd:twoarguments"] = { en = "\\...#1#2" }, - ["cd:threearguments"] = { en = "\\...#1#2#3" }, - ["cd:braces-s"] = { en = "{...}", lua = '"..."' }, - ["cd:braces-l"] = { en = "{...,...}", lua = '".. ... .."' }, - ["cd:brackets-s"] = { en = "[...]", lua = "{ ... }" }, - ["cd:brackets-l"] = { en = "[...,...]", lua = "{..., ...}" }, - ["cd:parenthesis-s"] = { en = "(...)" }, - ["cd:parenthesis-l"] = { en = "(...,...)" }, - ["cd:index-s"] = { en = "{...}" }, - ["cd:index-l"] = { en = "{..+...+..}" }, - ["cd:math-s"] = { en = "$...$" }, - ["cd:math-l"] = { en = "$...$" }, - ["cd:inlinemath-s"] = { en = "$...$" }, - ["cd:inlinemath-l"] = { en = "$...$" }, - ["cd:displaymath-s"] = { en = "$$...$$" }, - ["cd:displaymath-l"] = { en = "$$...$$" }, - ["cd:template-s"] = { en = "[|...|]" }, - ["cd:template-l"] = { en = "[|...|...|]" }, - ["cd:twowords-s"] = { en = "[..+..]" }, - ["cd:twowords-l"] = { en = "[..+..]" }, - ["cd:threewords-s"] = { en = "[..+..+..]" }, - ["cd:threewords-l"] = { en = "[..+..+..]" }, - ["cd:angle-s"] = { en = "<<...>>" }, - ["cd:angle-l"] = { en = "<<...>>" }, - ["cd:reference-s"] = { en = "[...]", lua = "{ ... }" }, - ["cd:reference-l"] = { en = "[...,...]", lua = "{..., ...}" }, - ["cd:position-s"] = { en = "(...)" }, - ["cd:position-l"] = { en = "(...,...)" }, - ["cd:triplet-s"] = { en = "[x:y:z]" }, - ["cd:triplet-l"] = { en = "[x:y:z,..]" }, - ["cd:word-s"] = { en = "{...}", lua = '"..."' }, - ["cd:word-l"] = { en = "{.. ... ..}", lua = '".. ... .."' }, - ["cd:content-s"] = { en = "{...}", lua = '"..."' }, - ["cd:content-l"] = { en = "{.. ... ..}", lua = '".. ... .."' }, - ["cd:textual-s"] = { en = "..." }, - ["cd:textual-l"] = { en = ".. ... .." }, - ["cd:none-s"] = { en = "..." }, - ["cd:none-l"] = { en = ".. ... .." }, - ["cd:macro-s"] = { en = "\\... " }, - ["cd:macro-l"] = { en = "\\... " }, - ["cd:to-s"] = { en = "\\to " }, - ["cd:to-l"] = { en = "\\to " }, - ["cd:destination-s"] = { en = "[{..[ref]}]" }, - ["cd:destination-l"] = { en = "[..,{..[ref,..]},..]" }, - ["cd:nothing-s"] = { en = "..." }, - ["cd:nothing-l"] = { en = "..." }, - ["cd:file-s"] = { en = " ... " }, - ["cd:file-l"] = { en = " ... " }, - ["cd:assignment-s"] = { en = "[..=..]", lua = "{ ..=.. } " }, - ["cd:assignment-l"] = { en = "[..,..=..,..]", lua = "{ ..,..=..,.. } " }, - ["cd:assignmentbraces-s"] = { en = "{..=..}" }, - ["cd:assignmentbraces-l"] = { en = "{..,..=..,..}" }, - ["cd:assignmentbrackets-s"] = { en = "[..=..]", lua = "{ ..=.. } " }, - ["cd:assignmentbrackets-l"] = { en = "[..,..=..,..]", lua = "{ ..,..=..,.. } " }, - ["cd:assignmentparentheses-s"] = { en = "(..=..)" }, - ["cd:assignmentparentheses-l"] = { en = "(..,..=..,..)" }, - ["cd:apply-s"] = { en = "[..=>..]" }, - ["cd:apply-l"] = { en = "[..,..=>..,..]" }, - ["cd:if-s"] = { en = "\\if... " }, - ["cd:if-l"] = { en = "\\if... " }, - ["cd:case-s"] = { en = "\\case " }, - ["cd:case-l"] = { en = "\\case " }, - ["cd:else-s"] = { en = "\\else " }, - ["cd:else-l"] = { en = "\\else " }, - ["cd:or-s"] = { en = "\\or " }, - ["cd:or-l"] = { en = "\\or " }, - ["cd:fi-s"] = { en = "\\fi " }, - ["cd:fi-l"] = { en = "\\fi " }, - ["cd:par-s"] = { en = "\\par " }, - ["cd:par-l"] = { en = "\\par " }, - ["cd:sep-s"] = { en = "\\" }, - ["cd:sep-l"] = { en = "\\" }, - } + }, } diff --git a/tex/context/base/mkiv/mult-low.lua b/tex/context/base/mkiv/mult-low.lua index b0d2bf2fc..b2abb0cc9 100644 --- a/tex/context/base/mkiv/mult-low.lua +++ b/tex/context/base/mkiv/mult-low.lua @@ -188,7 +188,7 @@ return { "sixthargumentfalse", "sixthargumenttrue", "seventhargumentfalse", "seventhargumenttrue", -- - "vkern", "hkern", + "vkern", "hkern", "vpenalty", "hpenalty", -- "doglobal", "dodoglobal", "redoglobal", "resetglobal", -- diff --git a/tex/context/base/mkiv/node-aux.lua b/tex/context/base/mkiv/node-aux.lua index 88acdf3c5..4df41d61b 100644 --- a/tex/context/base/mkiv/node-aux.lua +++ b/tex/context/base/mkiv/node-aux.lua @@ -22,7 +22,6 @@ local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local attributelist_code = nodecodes.attributelist -- temporary local localpar_code = nodecodes.localpar -local ligatureglyph_code = nodes.glyphcodes.ligature local nuts = nodes.nuts local tonut = nuts.tonut @@ -48,7 +47,6 @@ local setlink = nuts.setlink local setlist = nuts.setlist local setnext = nuts.setnext local setprev = nuts.setprev -local setcomponents = nuts.setcomponents local setattrlist = nuts.setattrlist local traversers = nuts.traversers @@ -382,162 +380,6 @@ function nodes.rehpack(n,...) rehpack(tonut(n),...) end -if CONTEXTLMTXMODE > 0 then - - local fastcopy = table.fastcopy - local getprop = nuts.getprop - local setprop = nuts.setprop - - local function set_components(base,list) - local t = { } - local n = 0 - while list do - local char = isglyph(list) - if char then - n = n + 1 - t[n] = char - end - list = getnext(list) - end - setprop(base,"components",n > 0 and t or false) - end - - local function get_components(base) - return getprop(base,"components") - end - - local function copy_no_components(base) - local copy = copy_node(base) - setprop(copy,"components",false) -- no metatable lookup! - return copy - end - - local function copy_only_glyphs(base) - local t = getprop(base,"components") -- also metatable - if t then - return fastcopy(t) - end - end - - local function do_count(t,marks) - local n = 0 - if t then - for i=1,#t do - local c = t[i] - if type(c) == "table" then - n = n + do_count(t,marks) - elseif not marks[c] then - n = n + 1 - else - --marks don't count - end - end - end - return n - end - - -- start is a mark and we need to keep that one - - local done = false - - local function count_components(base,marks) - local char = isglyph(base) - if char then - if getsubtype(base) == ligatureglyph_code then - if not done then - logs.report("fonts","!") - logs.report("fonts","! check count_components with mkiv !") - logs.report("fonts","!") - done = true - end - local t = getprop(base,"components") - if t then - return do_count(t,marks) - end - elseif not marks[char] then - return 1 - end - end - return 0 - end - - nuts.set_components = set_components - nuts.get_components = get_components - nuts.copy_only_glyphs = copy_only_glyphs - nuts.copy_no_components = copy_no_components - nuts.count_components = count_components - -else - - local get_components = node.direct.getcomponents - local set_components = node.direct.setcomponents - - local function copy_no_components(g,copyinjection) - local components = get_components(g) - if components then - set_components(g) - local n = copy_node(g) - if copyinjection then - copyinjection(n,g) - end - set_components(g,components) - -- maybe also upgrade the subtype but we don't use it anyway - return n - else - local n = copy_node(g) - if copyinjection then - copyinjection(n,g) - end - return n - end - end - - local function copy_only_glyphs(current) - local head = nil - local previous = nil - for n in nextglyph, current do - n = copy_node(n) - if head then - setlink(previous,n) - else - head = n - end - previous = n - end - return head - end - - -- start is a mark and we need to keep that one - - local function count_components(start,marks) - local char = isglyph(start) - if char then - if getsubtype(start) == ligatureglyph_code then - local n = 0 - local components = get_components(start) - while components do - n = n + count_components(components,marks) - components = getnext(components) - end - return n - elseif not marks[char] then - return 1 - end - end - return 0 - end - - nuts.set_components = set_components - nuts.get_components = get_components - nuts.copy_only_glyphs = copy_only_glyphs - nuts.copy_no_components = copy_no_components - nuts.count_components = count_components - -end - -nuts.setcomponents = function() report_error("unsupported: %a","setcomponents") end -nuts.getcomponents = function() report_error("unsupported: %a","getcomponents") end - do local localparcodes = nodes.localparcodes diff --git a/tex/context/base/mkiv/node-cmp.lmt b/tex/context/base/mkiv/node-cmp.lmt new file mode 100644 index 000000000..e9e7e266d --- /dev/null +++ b/tex/context/base/mkiv/node-cmp.lmt @@ -0,0 +1,243 @@ +if not modules then modules = { } end modules ['node-cmp'] = { + version = 1.001, + comment = "companion to node-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is a LuaTeX compatibility module. The code below is no longer +-- present in node-met or node-aux. These functions are rarely used. + +if node.count then + return +end + +local type = type + +local node = node +local direct = node.direct +local todirect = direct.tovaliddirect +local tonode = direct.tonode + +local count = direct.count +local length = direct.length +local slide = direct.slide + +function node.count(id,first,last) + return count(id,first and todirect(first), last and todirect(last) or nil) +end + +function node.length(first,last) + return length(first and todirect(first), last and todirect(last) or nil) +end + +function node.slide(n) + if n then + n = slide(todirect(n)) + if n then + return tonode(n) + end + end + return nil +end + +local hyphenating = direct.hyphenating +local ligaturing = direct.ligaturing +local kerning = direct.kerning + +-- kind of inconsistent + +function node.hyphenating(first,last) + if first then + local h, t = hyphenating(todirect(first), last and todirect(last) or nil) + return h and tonode(h) or nil, t and tonode(t) or nil, true + else + return nil, false + end +end + +function node.ligaturing(first,last) + if first then + local h, t = ligaturing(todirect(first), last and todirect(last) or nil) + return h and tonode(h) or nil, t and tonode(t) or nil, true + else + return nil, false + end +end + +function node.kerning(first,last) + if first then + local h, t = kerning(todirect(first), last and todirect(last) or nil) + return h and tonode(h) or nil, t and tonode(t) or nil, true + else + return nil, false + end + end + +local protect_glyph = direct.protect_glyph +local unprotect_glyph = direct.unprotect_glyph +local protect_glyphs = direct.protect_glyphs +local unprotect_glyphs = direct.unprotect_glyphs + +function node.protect_glyphs(first,last) + protect_glyphs(todirect(first), last and todirect(last) or nil) +end + +function node.unprotect_glyphs(first,last) + unprotect_glyphs(todirect(first), last and todirect(last) or nil) +end + +function node.protect_glyph(first) + protect_glyph(todirect(first)) +end + +function node.unprotect_glyph(first) + unprotect_glyph(todirect(first)) +end + +local flatten_discretionaries = direct.flatten_discretionaries +local check_discretionaries = direct.check_discretionaries +local check_discretionary = direct.check_discretionary + +function node.flatten_discretionaries(first) + local h, count = flatten_discretionaries(todirect(first)) + return tonode(h), count +end + +function node.check_discretionaries(n) + check_discretionaries(todirect(n)) +end + +function node.check_discretionary(n) + check_discretionary(todirect(n)) +end + +local hpack = direct.hpack +local vpack = direct.vpack +local list_to_hlist = direct.mlist_to_hlist + +function node.hpack(head,...) + local h, badness = hpack(head and todirect(head) or nil,...) + return tonode(h), badness +end + +function node.vpack(head,...) + local h, badness = vpack(head and todirect(head) or nil,...) + return tonode(h), badness +end + +function node.mlist_to_hlist(head,...) + return tonode(mlist_to_hlist(head and todirect(head) or nil,...)) +end + +local end_of_math = direct.end_of_math +local find_attribute = direct.find_attribute +local first_glyph = direct.first_glyph + +function node.end_of_math(n) + if n then + n = end_of_math(todirect(n)) + if n then + return tonode(n) + end + end + return nil +end + +function node.find_attribute(n,a) + if n then + local v, n = find_attribute(todirect(n),a) + if n then + return v, tonode(n) + end + end + return nil +end + +function node.first_glyph(first,last) + local n = first_glyph(todirect(first), last and todirect(last) or nil) + return n and tonode(n) or nil +end + +local dimensions = direct.dimensions +local rangedimensions = direct.rangedimensions +local effective_glue = direct.effective_glue + +function node.dimensions(a,b,c,d,e) + if type(a) == "userdata" then + a = todirect(a) + if type(b) == "userdata" then + b = todirect(b) + end + return dimensions(a,b) + else + d = todirect(d) + if type(e) == "userdata" then + e = todirect(e) + end + return dimensions(a,b,c,d,e) + end + return 0, 0, 0 +end + +function node.rangedimensions(parent,first,last) + return rangedimenensions(todirect(parent),todirect(first),last and todirect(last)) +end + +function node.effective_glue(list,parent) + return effective_glue(list and todirect(list) or nil,parent and todirect(parent) or nil) +end + +local uses_font = direct.uses_font +local has_glyph = direct.has_glyph +local protrusion_skippable = direct.protrusion_skippable +local prepend_prevdepth = direct.prepend_prevdepth +local make_extensible = direct.make_extensible + +function node.uses_font(n,f) + return uses_font(todirect(n),f) +end + +function node.has_glyph(n) + return has_glyph(todirect(n)) +end + +function node.protrusion_skippable(n) + return protrusion_skippable(todirect(n)) +end + +function node.prepend_prevdepth(n) + local n, d = prepend_prevdepth(todirect(n)) + return tonode(n), d +end + +function node.make_extensible(...) + local n = make_extensible(...) + return n and tonode(n) or nil +end + +local last_node = direct.last_node + +function node.last_node() + local n = last_node() + return n and tonode(n) or nil +end + +local is_zero_glue = direct.is_zero_glue +local getglue = direct.getglue +local setglue = direct.setglue + +function node.is_zero_glue(n) + return is_zero_glue(todirect(n)) +end + +function node.get_glue(n) + return get_glue(todirect(n)) +end + +function node.set_glue(n) + return set_glue(todirect(n)) +end + +node.family_font = tex.getfontoffamily diff --git a/tex/context/base/mkiv/node-cmp.lua b/tex/context/base/mkiv/node-cmp.lua deleted file mode 100644 index e9e7e266d..000000000 --- a/tex/context/base/mkiv/node-cmp.lua +++ /dev/null @@ -1,243 +0,0 @@ -if not modules then modules = { } end modules ['node-cmp'] = { - version = 1.001, - comment = "companion to node-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- This is a LuaTeX compatibility module. The code below is no longer --- present in node-met or node-aux. These functions are rarely used. - -if node.count then - return -end - -local type = type - -local node = node -local direct = node.direct -local todirect = direct.tovaliddirect -local tonode = direct.tonode - -local count = direct.count -local length = direct.length -local slide = direct.slide - -function node.count(id,first,last) - return count(id,first and todirect(first), last and todirect(last) or nil) -end - -function node.length(first,last) - return length(first and todirect(first), last and todirect(last) or nil) -end - -function node.slide(n) - if n then - n = slide(todirect(n)) - if n then - return tonode(n) - end - end - return nil -end - -local hyphenating = direct.hyphenating -local ligaturing = direct.ligaturing -local kerning = direct.kerning - --- kind of inconsistent - -function node.hyphenating(first,last) - if first then - local h, t = hyphenating(todirect(first), last and todirect(last) or nil) - return h and tonode(h) or nil, t and tonode(t) or nil, true - else - return nil, false - end -end - -function node.ligaturing(first,last) - if first then - local h, t = ligaturing(todirect(first), last and todirect(last) or nil) - return h and tonode(h) or nil, t and tonode(t) or nil, true - else - return nil, false - end -end - -function node.kerning(first,last) - if first then - local h, t = kerning(todirect(first), last and todirect(last) or nil) - return h and tonode(h) or nil, t and tonode(t) or nil, true - else - return nil, false - end - end - -local protect_glyph = direct.protect_glyph -local unprotect_glyph = direct.unprotect_glyph -local protect_glyphs = direct.protect_glyphs -local unprotect_glyphs = direct.unprotect_glyphs - -function node.protect_glyphs(first,last) - protect_glyphs(todirect(first), last and todirect(last) or nil) -end - -function node.unprotect_glyphs(first,last) - unprotect_glyphs(todirect(first), last and todirect(last) or nil) -end - -function node.protect_glyph(first) - protect_glyph(todirect(first)) -end - -function node.unprotect_glyph(first) - unprotect_glyph(todirect(first)) -end - -local flatten_discretionaries = direct.flatten_discretionaries -local check_discretionaries = direct.check_discretionaries -local check_discretionary = direct.check_discretionary - -function node.flatten_discretionaries(first) - local h, count = flatten_discretionaries(todirect(first)) - return tonode(h), count -end - -function node.check_discretionaries(n) - check_discretionaries(todirect(n)) -end - -function node.check_discretionary(n) - check_discretionary(todirect(n)) -end - -local hpack = direct.hpack -local vpack = direct.vpack -local list_to_hlist = direct.mlist_to_hlist - -function node.hpack(head,...) - local h, badness = hpack(head and todirect(head) or nil,...) - return tonode(h), badness -end - -function node.vpack(head,...) - local h, badness = vpack(head and todirect(head) or nil,...) - return tonode(h), badness -end - -function node.mlist_to_hlist(head,...) - return tonode(mlist_to_hlist(head and todirect(head) or nil,...)) -end - -local end_of_math = direct.end_of_math -local find_attribute = direct.find_attribute -local first_glyph = direct.first_glyph - -function node.end_of_math(n) - if n then - n = end_of_math(todirect(n)) - if n then - return tonode(n) - end - end - return nil -end - -function node.find_attribute(n,a) - if n then - local v, n = find_attribute(todirect(n),a) - if n then - return v, tonode(n) - end - end - return nil -end - -function node.first_glyph(first,last) - local n = first_glyph(todirect(first), last and todirect(last) or nil) - return n and tonode(n) or nil -end - -local dimensions = direct.dimensions -local rangedimensions = direct.rangedimensions -local effective_glue = direct.effective_glue - -function node.dimensions(a,b,c,d,e) - if type(a) == "userdata" then - a = todirect(a) - if type(b) == "userdata" then - b = todirect(b) - end - return dimensions(a,b) - else - d = todirect(d) - if type(e) == "userdata" then - e = todirect(e) - end - return dimensions(a,b,c,d,e) - end - return 0, 0, 0 -end - -function node.rangedimensions(parent,first,last) - return rangedimenensions(todirect(parent),todirect(first),last and todirect(last)) -end - -function node.effective_glue(list,parent) - return effective_glue(list and todirect(list) or nil,parent and todirect(parent) or nil) -end - -local uses_font = direct.uses_font -local has_glyph = direct.has_glyph -local protrusion_skippable = direct.protrusion_skippable -local prepend_prevdepth = direct.prepend_prevdepth -local make_extensible = direct.make_extensible - -function node.uses_font(n,f) - return uses_font(todirect(n),f) -end - -function node.has_glyph(n) - return has_glyph(todirect(n)) -end - -function node.protrusion_skippable(n) - return protrusion_skippable(todirect(n)) -end - -function node.prepend_prevdepth(n) - local n, d = prepend_prevdepth(todirect(n)) - return tonode(n), d -end - -function node.make_extensible(...) - local n = make_extensible(...) - return n and tonode(n) or nil -end - -local last_node = direct.last_node - -function node.last_node() - local n = last_node() - return n and tonode(n) or nil -end - -local is_zero_glue = direct.is_zero_glue -local getglue = direct.getglue -local setglue = direct.setglue - -function node.is_zero_glue(n) - return is_zero_glue(todirect(n)) -end - -function node.get_glue(n) - return get_glue(todirect(n)) -end - -function node.set_glue(n) - return set_glue(todirect(n)) -end - -node.family_font = tex.getfontoffamily diff --git a/tex/context/base/mkiv/node-gcm.lmt b/tex/context/base/mkiv/node-gcm.lmt new file mode 100644 index 000000000..2b5b24369 --- /dev/null +++ b/tex/context/base/mkiv/node-gcm.lmt @@ -0,0 +1,107 @@ +if not modules then modules = { } end modules ['node-gmc'] = { + version = 1.001, + comment = "companion to node-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type, tostring = type, tostring + +local nodes = nodes +local ligature_code = nodes.glyphcodes.ligature +local nuts = nodes.nuts + +local getnext = nuts.getnext +local getsubtype = nuts.getsubtype +local copy_node = nuts.copy +local count = nuts.count +local isglyph = nuts.isglyph +local getprop = nuts.getprop +local setprop = nuts.setprop + +local fastcopy = table.fastcopy + +local report_error = logs.reporter("node-aux:error") + +local function set_components(base,list) + local t = { } + local n = 0 + while list do + local char = isglyph(list) + if char then + n = n + 1 + t[n] = char + end + list = getnext(list) + end + setprop(base,"components",n > 0 and t or false) +end + +local function get_components(base) + return getprop(base,"components") +end + +local function copy_no_components(base) + local copy = copy_node(base) + setprop(copy,"components",false) -- no metatable lookup! + return copy +end + +local function copy_only_glyphs(base) + local t = getprop(base,"components") -- also metatable + if t then + return fastcopy(t) + end +end + +local function do_count(t,marks) + local n = 0 + if t then + for i=1,#t do + local c = t[i] + if type(c) == "table" then + n = n + do_count(t,marks) + elseif not marks[c] then + n = n + 1 + else + --marks don't count + end + end + end + return n +end + +-- start is a mark and we need to keep that one + +local done = false + +local function count_components(base,marks) + local char = isglyph(base) + if char then + if getsubtype(base) == ligature_code then + if not done then + logs.report("fonts","!") + logs.report("fonts","! check count_components with mkiv !") + logs.report("fonts","!") + done = true + end + local t = getprop(base,"components") + if t then + return do_count(t,marks) + end + elseif not marks[char] then + return 1 + end + end + return 0 +end + +nuts.set_components = set_components +nuts.get_components = get_components +nuts.copy_only_glyphs = copy_only_glyphs +nuts.copy_no_components = copy_no_components +nuts.count_components = count_components + +nuts.setcomponents = function() report_error("unsupported: %a","setcomponents") end +nuts.getcomponents = function() report_error("unsupported: %a","getcomponents") end diff --git a/tex/context/base/mkiv/node-gcm.lua b/tex/context/base/mkiv/node-gcm.lua new file mode 100644 index 000000000..1085f637f --- /dev/null +++ b/tex/context/base/mkiv/node-gcm.lua @@ -0,0 +1,91 @@ +if not modules then modules = { } end modules ['node-gmc'] = { + version = 1.001, + comment = "companion to node-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type, tostring = type, tostring + +local nodes = nodes +local nodecodes = nodes.nodecodes +local ligature_code = nodes.glyphcodes.ligature +local nuts = nodes.nuts + +local getnext = nuts.getnext +local getsubtype = nuts.getsubtype +local getprev = nuts.getprev +local setlink = nuts.setlink +local nextglyph = nuts.traversers.glyph +local copy_node = nuts.copy +local isglyph = nuts.isglyph + +local report_error = logs.reporter("node-aux:error") + +local get_components = node.direct.getcomponents +local set_components = node.direct.setcomponents + +local function copy_no_components(g,copyinjection) + local components = get_components(g) + if components then + set_components(g) + local n = copy_node(g) + if copyinjection then + copyinjection(n,g) + end + set_components(g,components) + -- maybe also upgrade the subtype but we don't use it anyway + return n + else + local n = copy_node(g) + if copyinjection then + copyinjection(n,g) + end + return n + end +end + +local function copy_only_glyphs(current) + local head = nil + local previous = nil + for n in nextglyph, current do + n = copy_node(n) + if head then + setlink(previous,n) + else + head = n + end + previous = n + end + return head +end + +-- start is a mark and we need to keep that one + +local function count_components(start,marks) + local char = isglyph(start) + if char then + if getsubtype(start) == ligature_code then + local n = 0 + local components = get_components(start) + while components do + n = n + count_components(components,marks) + components = getnext(components) + end + return n + elseif not marks[char] then + return 1 + end + end + return 0 +end + +nuts.set_components = set_components +nuts.get_components = get_components +nuts.copy_only_glyphs = copy_only_glyphs +nuts.copy_no_components = copy_no_components +nuts.count_components = count_components + +nuts.setcomponents = function() report_error("unsupported: %a","setcomponents") end +nuts.getcomponents = function() report_error("unsupported: %a","getcomponents") end diff --git a/tex/context/base/mkiv/node-ini.mkiv b/tex/context/base/mkiv/node-ini.mkiv index 5bf53cd2d..231a8524e 100644 --- a/tex/context/base/mkiv/node-ini.mkiv +++ b/tex/context/base/mkiv/node-ini.mkiv @@ -18,7 +18,7 @@ \newcount\filterstate \filterstate\plusone % hm, public \ifcase\contextlmtxmode \else - \registerctxluafile{node-cmp}{} + \registerctxluafile{node-cmp}{autosuffix} \fi \registerctxluafile{node-ini}{} @@ -27,6 +27,7 @@ \registerctxluafile{node-res}{} %registerctxluafile{node-ppt}{} % experimental, not used so probably useless \registerctxluafile{node-aux}{} +\registerctxluafile{node-gcm}{autosuffix} \registerctxluafile{node-tst}{} \registerctxluafile{node-tra}{} % we might split it off (module) \registerctxluafile{node-snp}{} diff --git a/tex/context/base/mkiv/pack-ori.lmt b/tex/context/base/mkiv/pack-ori.lmt new file mode 100644 index 000000000..a786b19ef --- /dev/null +++ b/tex/context/base/mkiv/pack-ori.lmt @@ -0,0 +1,70 @@ +if not modules then modules = { } end modules ['pack-ori'] = { + version = 1.001, + comment = "companion to supp-box.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local context = context +local implement = interfaces.implement +local variables = interfaces.variables + +local settings_to_array = utilities.parsers.settings_to_array + +local orientation = { + [variables.up] = 0x000, + [variables.left] = 0x001, + [variables.down] = 0x002, + [variables.right] = 0x003, + [variables.top] = 0x004, + [variables.bottom] = 0x005, +} +local vertical = { + [variables.line] = 0x000, + [variables.top] = 0x010, + [variables.bottom] = 0x020, + [variables.middle] = 0x030, +} +local horizontal = { + [variables.middle] = 0x000, + [variables.flushleft] = 0x100, + [variables.flushright] = 0x200, + [variables.left] = 0x300, + [variables.right] = 0x400, +} + +implement { + name = "toorientation", + public = true, + arguments = { + { + { "horizontal", "string" }, + { "vertical", "string" }, + { "orientation", "string" }, + } + }, + actions = function(t) + local n = 0 + local m = t.horizontal if m then n = n | (horizontal [m] or 0) end + local m = t.vertical if m then n = n | (vertical [m] or 0) end + local m = t.orientation if m then n = n | (orientation[m] or 0) end + -- logs.report("orientation","0x%03X : %s",n,table.sequenced(t)) + context(n) + end, +} + +implement { + name = "stringtoorientation", + public = true, + arguments = "string", + actions = function(s) + local n = 0 + local t = settings_to_array(s) + local m = t[1] if m then n = n | (horizontal [m] or 0) end + local m = t[2] if m then n = n | (vertical [m] or 0) end + local m = t[3] if m then n = n | (orientation[m] or 0) end + -- logs.report("orientation","0x%03X : %s",n,s) + context(n) + end, +} diff --git a/tex/context/base/mkiv/pack-ori.lua b/tex/context/base/mkiv/pack-ori.lua deleted file mode 100644 index a786b19ef..000000000 --- a/tex/context/base/mkiv/pack-ori.lua +++ /dev/null @@ -1,70 +0,0 @@ -if not modules then modules = { } end modules ['pack-ori'] = { - version = 1.001, - comment = "companion to supp-box.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local context = context -local implement = interfaces.implement -local variables = interfaces.variables - -local settings_to_array = utilities.parsers.settings_to_array - -local orientation = { - [variables.up] = 0x000, - [variables.left] = 0x001, - [variables.down] = 0x002, - [variables.right] = 0x003, - [variables.top] = 0x004, - [variables.bottom] = 0x005, -} -local vertical = { - [variables.line] = 0x000, - [variables.top] = 0x010, - [variables.bottom] = 0x020, - [variables.middle] = 0x030, -} -local horizontal = { - [variables.middle] = 0x000, - [variables.flushleft] = 0x100, - [variables.flushright] = 0x200, - [variables.left] = 0x300, - [variables.right] = 0x400, -} - -implement { - name = "toorientation", - public = true, - arguments = { - { - { "horizontal", "string" }, - { "vertical", "string" }, - { "orientation", "string" }, - } - }, - actions = function(t) - local n = 0 - local m = t.horizontal if m then n = n | (horizontal [m] or 0) end - local m = t.vertical if m then n = n | (vertical [m] or 0) end - local m = t.orientation if m then n = n | (orientation[m] or 0) end - -- logs.report("orientation","0x%03X : %s",n,table.sequenced(t)) - context(n) - end, -} - -implement { - name = "stringtoorientation", - public = true, - arguments = "string", - actions = function(s) - local n = 0 - local t = settings_to_array(s) - local m = t[1] if m then n = n | (horizontal [m] or 0) end - local m = t[2] if m then n = n | (vertical [m] or 0) end - local m = t[3] if m then n = n | (orientation[m] or 0) end - -- logs.report("orientation","0x%03X : %s",n,s) - context(n) - end, -} diff --git a/tex/context/base/mkiv/pack-ori.mkxl b/tex/context/base/mkiv/pack-ori.mkxl index 061768f94..5b2af1c4f 100644 --- a/tex/context/base/mkiv/pack-ori.mkxl +++ b/tex/context/base/mkiv/pack-ori.mkxl @@ -13,7 +13,7 @@ \writestatus{loading}{ConTeXt Packaging Macros / Anchoring} -\registerctxluafile{pack-ori}{} +\registerctxluafile{pack-ori}{autosuffix} \unprotect diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf index 9c05f8372..c0a7760c0 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 7f84d7523..84367c744 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/supp-ran.lua b/tex/context/base/mkiv/supp-ran.lua index 08889edf3..03da4262f 100644 --- a/tex/context/base/mkiv/supp-ran.lua +++ b/tex/context/base/mkiv/supp-ran.lua @@ -80,7 +80,8 @@ end -- maybe stack local function pushrandomseed() - insert(stack,last) + -- insert(stack,last) -- doesn't work okay + insert(stack,randomseed(last) or last) if trace_random or trace_details then report_system("pushing seed %s",last) end @@ -141,10 +142,9 @@ utilities.randomizer = { implement { name = "getrandomnumber", actions = { getrandomnumber, context }, arguments = { "integer", "integer" } } implement { name = "getrandomdimen", actions = { getrandomnumber, context }, arguments = { "dimen", "dimen" } } implement { name = "getrandomfloat", actions = { getrandomnumber, context }, arguments = { "number", "number" } } ---------- { name = "getmprandomnumber", actions = { getmprandomnumber, context } } -implement { name = "setrandomseed", actions = { setrandomseed }, arguments = "integer" } -implement { name = "getrandomseed", actions = { getrandomseed, context } } -implement { name = "pushrandomseed", actions = { pushrandomseed } } -implement { name = "poprandomseed", actions = { poprandomseed } } -implement { name = "reuserandomseed", actions = { reuserandomseed } } +implement { name = "getrandomseed", actions = { getrandomseed, context } } +implement { name = "setrandomseed", actions = setrandomseed, arguments = "integer" } +implement { name = "pushrandomseed", actions = pushrandomseed, public = true, } +implement { name = "poprandomseed", actions = poprandomseed, public = true, } +implement { name = "reuserandomseed", actions = reuserandomseed, public = true, } diff --git a/tex/context/base/mkiv/supp-ran.mkiv b/tex/context/base/mkiv/supp-ran.mkiv index 79efde79c..a616dd54f 100644 --- a/tex/context/base/mkiv/supp-ran.mkiv +++ b/tex/context/base/mkiv/supp-ran.mkiv @@ -13,22 +13,31 @@ \writestatus{loading}{ConTeXt Support Macros / Random Number Generation} -%D This module is downward compatible in the sense that we've kept -%D the user interface (which uses intermediate variables). +%D This module is downward compatible in the sense that we've kept the user +%D interface (which uses intermediate variables). +%D +%D \starttyping +%D \type{new}: \dorecurse{10}{\randomnumber{1}{100} }\par +%D \setrandomseed{24}\type{set}: \dorecurse{10}{\randomnumber{1}{100} }\par +%D \setrandomseed{24}\type{set}: \dorecurse{10}{\randomnumber{1}{100} }\par +%D \setrandomseed{24}\type{set}: \dorecurse{10}{\randomnumber{1}{100} }\par +%D \pushrandomseed \type{new}: \dorecurse{10}{\randomnumber{1}{100} }\par +%D \poprandomseed \type{old}: \dorecurse{10}{\randomnumber{1}{100} }\par +%D \type{new}: \dorecurse{10}{\randomnumber{1}{100} }\par +%D \stoptyping \registerctxluafile{supp-ran}{} \unprotect - \protected\def\getrandomcount #1#2#3{#1=\clf_getrandomnumber\numexpr#2\relax\numexpr#3\relax\relax} \protected\def\getrandomdimen #1#2#3{#1=\clf_getrandomdimen\dimexpr#2\relax\dimexpr#3\relax\scaledpoint\relax} \protected\def\getrandomnumber#1#2#3{\edef#1{\clf_getrandomnumber\numexpr#2\relax\numexpr#3\relax}} \protected\def\getrandomfloat #1#2#3{\edef#1{\clf_getrandomfloat\dimexpr#2\relax\dimexpr#3\relax}} \protected\def\setrandomseed #1{\clf_setrandomseed\numexpr#1\relax} \protected\def\getrandomseed #1{\edef#1{\clf_getrandomseed}} -\protected\def\pushrandomseed {\clf_pushrandomseed} -\protected\def\poprandomseed {\clf_poprandomseed} -\protected\def\reuserandomseed {\clf_reuserandomseed} % within push/pop +%protected\def\pushrandomseed {\clf_pushrandomseed} +%protected\def\poprandomseed {\clf_poprandomseed} +%protected\def\reuserandomseed {\clf_reuserandomseed} % within push/pop \let\freezerandomseed \pushrandomseed \let\defrostrandomseed\poprandomseed @@ -36,4 +45,5 @@ \def\randomnumber #1#2{\clf_getrandomnumber\numexpr#1\relax\numexpr#2\relax} \let\mprandomnumber \clf_getmprandomnumber + \protect \endinput diff --git a/tex/context/base/mkiv/syst-aux.lua b/tex/context/base/mkiv/syst-aux.lua index 4d81c4140..05a070d30 100644 --- a/tex/context/base/mkiv/syst-aux.lua +++ b/tex/context/base/mkiv/syst-aux.lua @@ -14,7 +14,6 @@ if not modules then modules = { } end modules ['syst-aux'] = { local tonumber, next, type = tonumber, next, type local utfsub = utf.sub local P, S, R, C, Cc, Cs, Carg, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Carg, lpeg.match -local next = next local find, formatters = string.find, string.formatters local context = context @@ -840,121 +839,3 @@ implement { public = true, actions = function() getshape("widowpenalties") end, } - -if CONTEXTLMTXMODE > 0 then - - -- This is kind of tricky and might not work for all csnames but as long as we use - -- it in a controlled way, we're okay. The engine implementation might be changed - -- a bit (no need to go through strings, but fetching a cs index and passing that - -- back also takes time). - - -- Another approach is to have the predefined stack operate use private stacks and - -- then the pop doesn't need the cs. But ... we then also need to store stuff in - -- the format so that complicates maters more than I'm willing to do. - - local insert, remove = table.insert, table.remove - - local push_macro = token.push_macro - local pop_macro = token.pop_macro - local scan_csname = token.scan_csname - - local stack = table.setmetatableindex("table") - - local report = logs.reporter("system","macrostack") - - local function pushmacro(name,global) - local s = push_macro(name,global) - if s then - insert(stack[name],s) - else - report("no macro %a",name) - insert(stack[name],false) - end - end - - local function popmacro(name) - local s = remove(stack[name]) - if s then - pop_macro(s) - else - -- error - end - end - - tokens.pushmacro = pushmacro - tokens.popmacro = popmacro - - interfaces.implement { - name = "localpushmacro", - public = true, - protected = true, - actions = function() - pushmacro(scan_csname()) - end - } - - interfaces.implement { - name = "globalpushmacro", - public = true, - protected = true, - actions = function() - pushmacro(scan_csname(),true) - end - } - - interfaces.implement { - name = "localpopmacro", - public = true, - protected = true, - actions = function() - popmacro(scan_csname()) - end - } - - interfaces.implement { - name = "globalpopmacro", - public = true, - protected = true, - actions = function() - popmacro(scan_csname()) - end - } - - interfaces.implement { - name = "showmacrostack", - public = true, - protected = true, - actions = function() - local n = scan_csname() - local s = stack[n] - local m = #s - report("%s : %i stack slots used",n,m) - for i=1,m do - report("% 3i %S",i,s[i]) - end - end - } - -end - --- For the moment here: - -if CONTEXTLMTXMODE > 0 then - - local create = token.create - local gobble = token.gobble - - implement { - name = "gobblenested", - public = true, - protected = true, - arguments = "3 strings", - actions = function(start,stop,command) - gobble(create(start),create(stop)) - if command then - context[command]() - end - end - } - -end diff --git a/tex/context/base/mkiv/syst-aux.mkiv b/tex/context/base/mkiv/syst-aux.mkiv index df74fb44f..1892605d6 100644 --- a/tex/context/base/mkiv/syst-aux.mkiv +++ b/tex/context/base/mkiv/syst-aux.mkiv @@ -12,6 +12,7 @@ %C details. \registerctxluafile{syst-aux}{} +\registerctxluafile{syst-mac}{} % A dedicated primitive \ifvoidmacro\cs == \ifx\cs\empty is some 10% faster but % probably not that noticeable in practice. An \ifvoidtoks might make sense but we diff --git a/tex/context/base/mkiv/syst-aux.mkxl b/tex/context/base/mkiv/syst-aux.mkxl index a85560989..42424dc75 100644 --- a/tex/context/base/mkiv/syst-aux.mkxl +++ b/tex/context/base/mkiv/syst-aux.mkxl @@ -12,6 +12,7 @@ %C details. \registerctxluafile{syst-aux}{} +\registerctxluafile{syst-mac}{autosuffix} %D This file is a follow up in \type {syst-aux.mkii} and \type {syst-aux.mkiv} where %D you can find some more pure \TEX\ or \LUATEX\ variants. There are quite some diff --git a/tex/context/base/mkiv/syst-ini.mkiv b/tex/context/base/mkiv/syst-ini.mkiv index acfcf7320..c978eaae5 100644 --- a/tex/context/base/mkiv/syst-ini.mkiv +++ b/tex/context/base/mkiv/syst-ini.mkiv @@ -997,8 +997,11 @@ %D Sometimes kerns make more sense than glue but we need to be in the %D right mode: -\protected\def\vkern{\ifhmode\par \fi\kern} -\protected\def\hkern{\ifvmode\dontleavehmode\fi\kern} +\protected\def\vkern {\ifhmode\par \fi\kern} +\protected\def\hkern {\ifvmode\dontleavehmode\fi\kern} + +\protected\def\vpenalty{\ifhmode\par \fi\penalty} +\protected\def\hpenalty{\ifvmode\dontleavehmode\fi\penalty} %D Again a few kind-of-extensions the core. These come from plain \TEX\ but %D are probably not used in \CONTEXT. diff --git a/tex/context/base/mkiv/syst-ini.mkxl b/tex/context/base/mkiv/syst-ini.mkxl index 1aa78f564..b3fe4374c 100644 --- a/tex/context/base/mkiv/syst-ini.mkxl +++ b/tex/context/base/mkiv/syst-ini.mkxl @@ -1009,8 +1009,11 @@ %D Sometimes kerns make more sense than glue but we need to be in the %D right mode: -\protected\def\vkern{\ifhmode\par \fi\kern} -\protected\def\hkern{\ifvmode\dontleavehmode\fi\kern} +\protected\def\vkern {\ifhmode\par \fi\kern} +\protected\def\hkern {\ifvmode\dontleavehmode\fi\kern} + +\protected\def\vpenalty{\ifhmode\par \fi\penalty} +\protected\def\hpenalty{\ifvmode\dontleavehmode\fi\penalty} %D Again a few kind-of-extensions the core. These come from plain \TEX\ but %D are probably not used in \CONTEXT. diff --git a/tex/context/base/mkiv/syst-lua.lmt b/tex/context/base/mkiv/syst-lua.lmt new file mode 100644 index 000000000..018231e30 --- /dev/null +++ b/tex/context/base/mkiv/syst-lua.lmt @@ -0,0 +1,315 @@ +if not modules then modules = { } end modules ['syst-lua'] = { + version = 1.001, + comment = "companion to syst-lua.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local load, type, tonumber = load, type, tonumber +local find = string.find +local concat = table.concat +local utfchar = utf.char +local S, C, P, lpegmatch, lpegtsplitat = lpeg.S, lpeg.C, lpeg.P, lpeg.match, lpeg.tsplitat + +local xmath = xmath or math +local xcomplex = xcomplex or { } + +local scan_next = token.scan_next or token.get_next +local scan_cmdchr = token.scan_cmdchr_expanded +local scan_token = token.scan_token + +local get_csname = token.get_csname +----- get_macro = token.get_macro +----- put_next = token.put_next + +local cmd = tokens.commands +local letter_code = cmd.letter +local other_char_code = cmd.other_char +local spacer_code = cmd.spacer +local other_char_code = cmd.other_char +local relax_code = cmd.relax +local register_int_code = cmd.register_int +local internal_int_code = cmd.internal_int +local register_dimen_code = cmd.register_dimen +local internal_dimen_code = cmd.internal_dimen +local register_glue_code = cmd.register_glue +local internal_glue_code = cmd.internal_glue +local register_toks_code = cmd.register_toks +local internal_toks_code = cmd.internal_toks +local char_given_code = cmd.char_given +local math_given_code = cmd.math_given +local xmath_given_code = cmd.xmath_given +local some_item_code = cmd.some_item +----- call_code = cmd.call +----- the_code = cmd.the +----- convert_code = cmd.convert +----- lua_expandable_call_code = cmd.lua_expandable_call + +local getdimen = tex.getdimen +local getglue = tex.getglue +local getcount = tex.getcount +local gettoks = tex.gettoks +local gettex = tex.get + +local context = context +commands = commands or { } +local commands = commands +local context = context +local implement = interfaces.implement +local dimenfactors = number.dimenfactors + +local ctx_protected_cs = context.protected.cs -- more efficient +local ctx_firstoftwoarguments = context.firstoftwoarguments +local ctx_secondoftwoarguments = context.secondoftwoarguments +local ctx_firstofoneargument = context.firstofoneargument +local ctx_gobbleoneargument = context.gobbleoneargument + +implement { -- will be overloaded later + name = "writestatus", + arguments = "2 strings", + actions = logs.status, +} + +function commands.doifelse(b) + if b then + ctx_firstoftwoarguments() + else + ctx_secondoftwoarguments() + end +end + +function commands.doifelsesomething(b) + if b and b ~= "" then + ctx_firstoftwoarguments() + else + ctx_secondoftwoarguments() + end +end + +function commands.doif(b) + if b then + ctx_firstofoneargument() + else + ctx_gobbleoneargument() + end +end + +function commands.doifsomething(b) + if b and b ~= "" then + ctx_firstofoneargument() + else + ctx_gobbleoneargument() + end +end + +function commands.doifnot(b) + if b then + ctx_gobbleoneargument() + else + ctx_firstofoneargument() + end +end + +function commands.doifnotthing(b) + if b and b ~= "" then + ctx_gobbleoneargument() + else + ctx_firstofoneargument() + end +end + +commands.testcase = commands.doifelse -- obsolete + +function commands.boolcase(b) + context(b and 1 or 0) +end + +function commands.doifelsespaces(str) + if find(str,"^ +$") then + ctx_firstoftwoarguments() + else + ctx_secondoftwoarguments() + end +end + +local pattern = lpeg.patterns.validdimen + +function commands.doifelsedimenstring(str) + if lpegmatch(pattern,str) then + ctx_firstoftwoarguments() + else + ctx_secondoftwoarguments() + end +end + +local p_first = C((1-P(",")-P(-1))^0) + +implement { + name = "firstinset", + arguments = "string", + actions = function(str) context(lpegmatch(p_first,str or "")) end, + public = true, +} + +implement { + name = "ntimes", + arguments = { "string", "integer" }, + actions = { string.rep, context } +} + +implement { + name = "execute", + arguments = "string", + actions = os.execute -- wrapped in sandbox +} + +implement { + name = "doifelsesame", + arguments = "2 strings", + actions = function(a,b) + if a == b then + ctx_firstoftwoarguments() + else + ctx_secondoftwoarguments() + end + end +} + +implement { + name = "doifsame", + arguments = "2 strings", + actions = function(a,b) + if a == b then + ctx_firstofoneargument() + else + ctx_gobbleoneargument() + end + end +} + +implement { + name = "doifnotsame", + arguments = "2 strings", + actions = function(a,b) + if a == b then + ctx_gobbleoneargument() + else + ctx_firstofoneargument() + end + end +} + +-- This is a bit of a joke as I never really needed floating point expressions (okay, +-- maybe only with scaling because there one can get numbers that are too large for +-- dimensions to deal with). Of course one can write a parser in \TEX\ speak but then +-- one also needs to implement a bunch of functions. It doesn't pay of so we just +-- stick to the next gimmick. It looks inefficient but performance is actually quite +-- efficient. + +do + + local result = { "return " } + local word = { } + local r = 1 + local w = 0 + + local report = logs.reporter("system","expression") + + local function unexpected(c) + report("unexpected token %a",c) + end + + local function unexpected(c) + report("unexpected token %a",c) + end + + local function expression() + local w = 0 + local r = 1 + while true do + local n, i = scan_cmdchr() + if n == letter_code then + w = w + 1 ; word[w] = utfchar(i) + else + if w > 0 then + -- we could use a metatable for all math, complex and factors + local s = concat(word,"",1,w) + local d = dimenfactors[s] + if d then + r = r + 1 ; result[r] = "*" + r = r + 1 ; result[r] = 1/d + else + if xmath[s] then + r = r + 1 ; result[r] = "xmath." + elseif xcomplex[s] then + r = r + 1 ; result[r] = "xcomplex." + end + r = r + 1 ; result[r] = s + end + w = 0 + end + if n == other_char_code then + r = r + 1 ; result[r] = utfchar(i) + elseif n == spacer_code then + -- r = r + 1 ; result[r] = " " + elseif n == relax_code then + break + elseif n == register_int_code or n == internal_int_code then + r = r + 1 ; result[r] = getcount(i) + elseif n == register_dimen_code or n == internal_dimen_code then + r = r + 1 ; result[r] = getdimen(i) + elseif n == register_glue_code or n == n == register_dimen_code_glue_code then + r = r + 1 ; result[r] = getglue(i) + elseif n == register_toks_code or n == n == register_dimen_code_toks_code then + r = r + 1 ; result[r] = gettoks(i) + elseif n == char_given_code or n == math_given_code or n == xmath_given_code then + r = r + 1 ; result[r] = i + elseif n == some_item_code then + local n = get_csname(t) + if n then + local s = gettex(n) + if s then + r = r + 1 ; result[r] = s + else + unexpected(c) + end + else + unexpected(c) + end + -- elseif n == call_code then + -- local n = get_csname(t) + -- if n then + -- local s = get_macro(n) + -- if s then + -- r = r + 1 ; result[r] = s + -- else + -- unexpected(c) + -- end + -- else + -- unexpected(c) + -- end + -- elseif n == the_code or n == convert_code or n == lua_expandable_call_code then + -- put_next(t) + -- scan_token() -- expands + else + unexpected(c) + end + end + end + local code = concat(result,"",1,r) + local func = load(code) + if type(func) == "function" then + context(func()) + else + report("invalid lua %a",code) + end + end + + implement { + public = true, + name = "expression", + actions = expression, + } + +end diff --git a/tex/context/base/mkiv/syst-lua.lua b/tex/context/base/mkiv/syst-lua.lua index 7e44b9f08..085f75eca 100644 --- a/tex/context/base/mkiv/syst-lua.lua +++ b/tex/context/base/mkiv/syst-lua.lua @@ -6,13 +6,43 @@ if not modules then modules = { } end modules ['syst-lua'] = { license = "see context related readme files" } +local load, type, tonumber = load, type, tonumber +local concat = table.concat +local utfchar = utf.char local find = string.find local S, C, P, lpegmatch, lpegtsplitat = lpeg.S, lpeg.C, lpeg.P, lpeg.match, lpeg.tsplitat -commands = commands or { } -local commands = commands -local context = context -local implement = interfaces.implement +local xmath = xmath or math +local xcomplex = xcomplex or { } + +local cmd = tokens.commands + +local scan_next = token.scan_next or token.get_next +local scan_cmdchr = token.scan_cmdchr_expanded + +local get_command = token.get_command +local get_mode = token.get_mode +local get_index = token.get_index +local get_csname = token.get_csname +local get_macro = token.get_macro + +local put_next = token.put_next + +local scan_token = token.scan_token or token.get_token + +local getdimen = tex.getdimen +local getglue = tex.getglue +local getcount = tex.getcount +local gettoks = tex.gettoks +local gettex = tex.get + +local context = context +local dimenfactors = number.dimenfactors + +commands = commands or { } +local commands = commands +local context = context +local implement = interfaces.implement local ctx_protected_cs = context.protected.cs -- more efficient local ctx_firstoftwoarguments = context.firstoftwoarguments @@ -162,53 +192,20 @@ implement { -- stick to the next gimmick. It looks inefficient but performance is actually quite -- efficient. -local concat = table.concat -local utfchar = utf.char -local load, type, tonumber = load, type, tonumber - -local xmath = xmath or math -local xcomplex = xcomplex or { } - -local cmd = tokens.commands - -local scan_next = token.scan_next or token.get_next -local scan_cmdchr = token.scan_cmdchr_expanded - -local get_command = token.get_command -local get_mode = token.get_mode -local get_index = token.get_index -local get_csname = token.get_csname -local get_macro = token.get_macro - -local put_next = token.put_next - -local scan_token = token.scan_token - -local getdimen = tex.getdimen -local getglue = tex.getglue -local getcount = tex.getcount -local gettoks = tex.gettoks -local gettex = tex.get - -local context = context -local dimenfactors = number.dimenfactors - -local result = { "return " } -local word = { } -local r = 1 -local w = 0 - -local report = logs.reporter("system","expression") +do -local function unexpected(c) - report("unexpected token %a",c) -end + local result = { "return " } + local word = { } + local r = 1 + local w = 0 -local expression + local report = logs.reporter("system","expression") -if CONTEXTLMTXMODE == 0 then + local function unexpected(c) + report("unexpected token %a",c) + end - expression = function() + local function expression() local w = 0 local r = 1 while true do @@ -292,120 +289,10 @@ if CONTEXTLMTXMODE == 0 then end end -else - - local letter_code = cmd.letter - local other_char_code = cmd.other_char - local spacer_code = cmd.spacer - local other_char_code = cmd.other_char - local relax_code = cmd.relax - local register_int_code = cmd.register_int - local internal_int_code = cmd.internal_int - local register_dimen_code = cmd.register_dimen - local internal_dimen_code = cmd.internal_dimen - local register_glue_code = cmd.register_glue - local internal_glue_code = cmd.internal_glue - local register_toks_code = cmd.register_toks - local internal_toks_code = cmd.internal_toks - local char_given_code = cmd.char_given - local math_given_code = cmd.math_given - local xmath_given_code = cmd.xmath_given - local some_item_code = cmd.some_item - -- local call_code = cmd.call - -- local the_code = cmd.the - -- local convert_code = cmd.convert - -- local lua_expandable_call_code = cmd.lua_expandable_call - - local function unexpected(c) - report("unexpected token %a",c) - end - - expression = function() - local w = 0 - local r = 1 - while true do - local n, i = scan_cmdchr() - if n == letter_code then - w = w + 1 ; word[w] = utfchar(i) - else - if w > 0 then - -- we could use a metatable for all math, complex and factors - local s = concat(word,"",1,w) - local d = dimenfactors[s] - if d then - r = r + 1 ; result[r] = "*" - r = r + 1 ; result[r] = 1/d - else - if xmath[s] then - r = r + 1 ; result[r] = "xmath." - elseif xcomplex[s] then - r = r + 1 ; result[r] = "xcomplex." - end - r = r + 1 ; result[r] = s - end - w = 0 - end - if n == other_char_code then - r = r + 1 ; result[r] = utfchar(i) - elseif n == spacer_code then - -- r = r + 1 ; result[r] = " " - elseif n == relax_code then - break - elseif n == register_int_code or n == internal_int_code then - r = r + 1 ; result[r] = getcount(i) - elseif n == register_dimen_code or n == internal_dimen_code then - r = r + 1 ; result[r] = getdimen(i) - elseif n == register_glue_code or n == n == register_dimen_code_glue_code then - r = r + 1 ; result[r] = getglue(i) - elseif n == register_toks_code or n == n == register_dimen_code_toks_code then - r = r + 1 ; result[r] = gettoks(i) - elseif n == char_given_code or n == math_given_code or n == xmath_given_code then - r = r + 1 ; result[r] = i - elseif n == some_item_code then - local n = get_csname(t) - if n then - local s = gettex(n) - if s then - r = r + 1 ; result[r] = s - else - unexpected(c) - end - else - unexpected(c) - end - -- elseif n == call_code then - -- local n = get_csname(t) - -- if n then - -- local s = get_macro(n) - -- if s then - -- r = r + 1 ; result[r] = s - -- else - -- unexpected(c) - -- end - -- else - -- unexpected(c) - -- end - -- elseif n == the_code or n == convert_code or n == lua_expandable_call_code then - -- put_next(t) - -- scan_token() -- expands - else - unexpected(c) - end - end - end - local code = concat(result,"",1,r) - local func = load(code) - if type(func) == "function" then - context(func()) - else - report("invalid lua %a",code) - end - end + implement { + public = true, + name = "expression", + actions = expression, + } end - -implement { - public = true, - name = "expression", - actions = expression, -} diff --git a/tex/context/base/mkiv/syst-lua.mkxl b/tex/context/base/mkiv/syst-lua.mkxl index 89d5ed6dd..d04e78392 100644 --- a/tex/context/base/mkiv/syst-lua.mkxl +++ b/tex/context/base/mkiv/syst-lua.mkxl @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\registerctxluafile{syst-lua}{} +\registerctxluafile{syst-lua}{autosuffix} \unprotect diff --git a/tex/context/base/mkiv/syst-mac.lmt b/tex/context/base/mkiv/syst-mac.lmt new file mode 100644 index 000000000..6fc8df2a4 --- /dev/null +++ b/tex/context/base/mkiv/syst-mac.lmt @@ -0,0 +1,117 @@ +if not modules then modules = { } end modules ['syst-mac'] = { + version = 1.001, + comment = "companion to syst-aux.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is kind of tricky and might not work for all csnames but as long as we use +-- it in a controlled way, we're okay. The engine implementation might be changed +-- a bit (no need to go through strings, but fetching a cs index and passing that +-- back also takes time). + +-- Another approach is to have the predefined stack operate use private stacks and +-- then the pop doesn't need the cs. But ... we then also need to store stuff in +-- the format so that complicates maters more than I'm willing to do. + +local insert, remove = table.insert, table.remove + +local push_macro = token.push_macro +local pop_macro = token.pop_macro +local scan_csname = token.scan_csname +local create_token = token.create +local gobble_token = token.gobble + +local context = context +local implement = interfaces.implement + +local report = logs.reporter("system","macrostack") + +local stack = table.setmetatableindex("table") + +local function pushmacro(name,global) + local s = push_macro(name,global) + if s then + insert(stack[name],s) + else + report("no macro %a",name) + insert(stack[name],false) + end +end + +local function popmacro(name) + local s = remove(stack[name]) + if s then + pop_macro(s) + else + -- error + end +end + +tokens.pushmacro = pushmacro +tokens.popmacro = popmacro + +implement { + name = "localpushmacro", + public = true, + protected = true, + actions = function() + pushmacro(scan_csname()) + end +} + +implement { + name = "globalpushmacro", + public = true, + protected = true, + actions = function() + pushmacro(scan_csname(),true) + end +} + +implement { + name = "localpopmacro", + public = true, + protected = true, + actions = function() + popmacro(scan_csname()) + end +} + +implement { + name = "globalpopmacro", + public = true, + protected = true, + actions = function() + popmacro(scan_csname()) + end +} + +implement { + name = "showmacrostack", + public = true, + protected = true, + actions = function() + local n = scan_csname() + local s = stack[n] + local m = #s + report("%s : %i stack slots used",n,m) + for i=1,m do + report("% 3i %S",i,s[i]) + end + end +} + +implement { + name = "gobblenested", + public = true, + protected = true, + arguments = "3 strings", + actions = function(start,stop,command) + gobble_token(create_token(start),create_token(stop)) + if command then + context[command]() + end + end +} diff --git a/tex/context/base/mkiv/syst-mac.lua b/tex/context/base/mkiv/syst-mac.lua new file mode 100644 index 000000000..b7c36817c --- /dev/null +++ b/tex/context/base/mkiv/syst-mac.lua @@ -0,0 +1,9 @@ +if not modules then modules = { } end modules ['syst-mac'] = { + version = 1.001, + comment = "companion to syst-aux.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- empty diff --git a/tex/context/base/mkiv/toks-aux.lua b/tex/context/base/mkiv/toks-aux.lua index 1cfc13af3..cce29a32a 100644 --- a/tex/context/base/mkiv/toks-aux.lua +++ b/tex/context/base/mkiv/toks-aux.lua @@ -5,84 +5,80 @@ if not modules then modules = { } end modules ['toks-aux'] = { license = "see context related readme files" } -if CONTEXTLMTXMODE > 0 then +local type, tostring = type, tostring +local max = math.max +local formatters, gsub = string.formatters, string.gsub - local type, tostring = type, tostring - local max = math.max - local formatters, gsub = string.formatters, string.gsub - - interfaces.implement { - name = "showluatokens", - public = true, - protected = true, - actions = function() - local f0 = formatters["%s: %s"] - local nl = logs.newline - local wr = logs.writer - local t = token.peek_next() -- local t = token.scan_next() token.put_back(t) - local n = "" - local w = "" - local c = t.cmdname - if c == "left_brace" then - w = "given token list" - t = token.scan_toks(false) - elseif c == "register_toks" then - token.scan_next() - w = "token register" - n = t.csname or t.index - t = tex.gettoks(n,true) - elseif c == "internal_toks" then - token.scan_next() - w = "internal token variable" - n = t.csname or t.index - t = tex.gettoks(n,true) +interfaces.implement { + name = "showluatokens", + public = true, + protected = true, + actions = function() + local f0 = formatters["%s: %s"] + local nl = logs.newline + local wr = logs.writer + local t = token.peek_next() -- local t = token.scan_next() token.put_back(t) + local n = "" + local w = "" + local c = t.cmdname + if c == "left_brace" then + w = "given token list" + t = token.scan_toks(false) + elseif c == "register_toks" then + token.scan_next() + w = "token register" + n = t.csname or t.index + t = tex.gettoks(n,true) + elseif c == "internal_toks" then + token.scan_next() + w = "internal token variable" + n = t.csname or t.index + t = tex.gettoks(n,true) + else + if t.protected then + w = "protected control sequence" else - if t.protected then - w = "protected control sequence" - else - w = "control sequence" - end - n = token.scan_csname() - t = token.get_meaning(n,true) + w = "control sequence" end - wr(f0(w,n)) - nl() - if type(t) == "table" then - local w1 = 4 - local w2 = 1 - local w3 = 3 - local w4 = 3 - for i=1,#t do - local ti = t[i] - w1 = max(w1,#tostring(ti.id)) - w2 = max(w2,#tostring(ti.command)) - w3 = max(w3,#tostring(ti.index)) - w4 = max(w4,#ti.cmdname) - end - local f1 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %s"] - local f2 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s"] - local f3 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %C"] - for i=1,#t do - local ti = t[i] - local cs = ti.csname - local id = ti.id - local ix = ti.index - local cd = ti.command - local cn = gsub(ti.cmdname,"_"," ") - if cs then - wr(f1(id,cd,ix,cn,cs)) - elseif cn == "letter" or cn == "other_char" then - wr(f3(id,cd,ix,cn,ix)) - else - wr(f2(id,cd,ix,cn)) - if cn == "end_match" then - wr("-------") - end + n = token.scan_csname() + t = token.get_meaning(n,true) + end + wr(f0(w,n)) + nl() + if type(t) == "table" then + local w1 = 4 + local w2 = 1 + local w3 = 3 + local w4 = 3 + for i=1,#t do + local ti = t[i] + w1 = max(w1,#tostring(ti.id)) + w2 = max(w2,#tostring(ti.command)) + w3 = max(w3,#tostring(ti.index)) + w4 = max(w4,#ti.cmdname) + end + local f1 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %s"] + local f2 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s"] + local f3 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %C"] + for i=1,#t do + local ti = t[i] + local cs = ti.csname + local id = ti.id + local ix = ti.index + local cd = ti.command + local cn = gsub(ti.cmdname,"_"," ") + if cs then + wr(f1(id,cd,ix,cn,cs)) + elseif cn == "letter" or cn == "other_char" then + wr(f3(id,cd,ix,cn,ix)) + else + wr(f2(id,cd,ix,cn)) + if cn == "end_match" then + wr("-------") end end - nl() end + nl() end - } - -end + end +} diff --git a/tex/context/base/mkiv/toks-aux.mkiv b/tex/context/base/mkiv/toks-aux.mkiv index 413b1f7c8..f66b51ec5 100644 --- a/tex/context/base/mkiv/toks-aux.mkiv +++ b/tex/context/base/mkiv/toks-aux.mkiv @@ -28,7 +28,9 @@ % \showluatokens\scratchtoks % \showluatokens\everypar -\registerctxluafile{toks-aux}{} +\ifcase\contextlmtxmode \or + \registerctxluafile{toks-aux}{autosuffix} +\fi \installcorenamespace {tokenlist} diff --git a/tex/context/base/mkiv/trac-vis.lua b/tex/context/base/mkiv/trac-vis.lua index 2d2fd4092..64038dc38 100644 --- a/tex/context/base/mkiv/trac-vis.lua +++ b/tex/context/base/mkiv/trac-vis.lua @@ -388,10 +388,10 @@ local c_skip_b = "trace:m" local c_glyph = "trace:o" local c_ligature = "trace:s" local c_white = "trace:w" -local c_math = "trace:s" -local c_origin = "trace:o" -local c_discretionary = "trace:d" -local c_expansion = "trace:o" +----- c_math = "trace:s" +----- c_origin = "trace:o" +----- c_discretionary = "trace:d" +----- c_expansion = "trace:o" local c_depth = "trace:o" local c_indent = "trace:s" @@ -409,8 +409,9 @@ local c_white_d = "trace:dw" local c_math_d = "trace:dr" local c_origin_d = "trace:do" local c_discretionary_d = "trace:dd" -local c_expansion_d = "trace:do" -local c_depth_d = "trace:do" +----- c_expansion_d = "trace:do" +----- c_depth_d = "trace:do" +----- c_indent_d = "trace:ds" local function sometext(str,layer,color,textcolor,lap) -- we can just paste verbatim together .. no typesteting needed local text = hpack_string(str,usedfont) @@ -889,7 +890,7 @@ local ruledglue do local tags = { -- [userskip_code] = "US", - [gluecodes.lineskip] = "LS", + [gluecodes.lineskip] = "LI", [gluecodes.baselineskip] = "BS", [gluecodes.parskip] = "PS", [gluecodes.abovedisplayskip] = "DA", diff --git a/tex/context/modules/mkiv/m-sql.mkiv b/tex/context/modules/mkiv/m-sql.mkiv index ed9dae99a..bb62610ea 100644 --- a/tex/context/modules/mkiv/m-sql.mkiv +++ b/tex/context/modules/mkiv/m-sql.mkiv @@ -17,8 +17,8 @@ \registerctxluafile{util-sql}{} \ifcase\contextlmtxmode\else - \registerctxluafile{libs-imp-mysql}{} - \registerctxluafile{libs-imp-sqlite}{} + \registerctxluafile{libs-imp-mysql}{autosuffix} + \registerctxluafile{libs-imp-sqlite}{autosuffix} \fi \setupmodule diff --git a/tex/context/modules/mkiv/m-steps.mkvi b/tex/context/modules/mkiv/m-steps.mkvi index 873015fd6..fb2000d40 100644 --- a/tex/context/modules/mkiv/m-steps.mkvi +++ b/tex/context/modules/mkiv/m-steps.mkvi @@ -428,12 +428,16 @@ \startxmlsetups xml:step:define \xmlsetsetup {#1} - {stepchart|steptable|stepaligntable|cells|texts|stepcell|cell|text} + {stepchart|steptable|stepaligntable|cells|texts|stepcell|cell|text|br} {xml:step:*} \stopxmlsetups \xmlregistersetup{xml:step:define} +\startxmlsetups xml:step:br + \crlf +\stopxmlsetups + \startxmlsetups xml:step:stepchart \startSTEPchart[\c!category=\xmlatt{#1}{class}] \xmlflush{#1} @@ -492,9 +496,17 @@ \stopxmlsetups \startxmlsetups xml:step:text - \text - [\xmlatt{#1}{class}] - {\xmlflush{#1}} + \doifelse {\xmlatt{#1}{option}} {paragraph} { + \text + [\xmlatt{#1}{class}] + {\framed + [\c!location=\v!middle,\c!align={\v!lohi,\v!flushleft},\c!offset=0pt,\c!frame=\v!no] + {\ignorespaces\xmlflush{#1}\removeunwantedspaces}} + } { + \text + [\xmlatt{#1}{class}] + {\xmlflush{#1}} + } \stopxmlsetups \protect @@ -519,11 +531,21 @@ \startbuffer - some cell - some text - some cell - some text - some cell + some cell A + some text 1 + some cell B + some text 2 + some cell C + +\stopbuffer + +\typebuffer \processxmlbuffer + +\startbuffer + + some cell A + some more
text 1
+ some cell B
\stopbuffer diff --git a/tex/context/modules/mkiv/s-system-visual.mkiv b/tex/context/modules/mkiv/s-system-visual.mkiv new file mode 100644 index 000000000..5b5107a2d --- /dev/null +++ b/tex/context/modules/mkiv/s-system-visual.mkiv @@ -0,0 +1,94 @@ +%D \module +%D [ file=s-system-visual.mkxl, +%D version=2020.07.15, +%D title=\CONTEXT\ Style File, +%D subtitle=System Visual Debugger Legend, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\startmodule[system-visual] + +\starttexdefinition unexpanded visuallegend + \begingroup + \switchtobodyfont[10pt] + \setuptabulate[before=,after=] + \hsize24cm + \scale + [width=\textwidth] + \bgroup + \forgetall + \startboxedcolumns[n=3,strut=no] + \starttabulate[|lT|l|] + \NC L__ \NC line box \NC \NR + \NC H__ \NC horizontal box \NC \NR + \NC _T_ \NC vertical top box \NC \NR + \NC __V \NC vertical box \NC \NR + \TB + \NC VK \NC vertical kern \NC \NR + \NC HK \NC horizontal kern \NC \NR + \NC MK \NC math kern \NC \NR + \NC MK \NC margin kern \NC \NR + \NC LK \NC math list kern \NC \NR + \TB + \NC VP \NC vertical penalty \NC \NR + \NC HP \NC horizontal penalty \NC \NR + \TB + \NC LI \NC line skip \NC \NR + \NC BS \NC baseline skip \NC \NR + \NC PS \NC par skip \NC \NR + \NC DA \NC abovedisplay skip \NC \NR + \NC DB \NC belowdisplay skip \NC \NR + \NC SA \NC above display short skip \NC \NR + \NC SB \NC below display short skip \NC \NR + \NC TS \NC top skip \NC \NR + \NC ST \NC split top skip \NC \NR + \NC AS \NC tab skip \NC \NR + \NC LH \NC left hang skip \NC \NR + \NC RH \NC right hang skip \NC \NR + \NC MS \NC thin mu skip \NC \NR + \NC MM \NC med mu skip \NC \NR + \NC ML \NC thick mu skip \NC \NR + \NC IM \NC inter math skip \NC \NR + \NC MT \NC math skip \NC \NR + \NC LS \NC left skip \NC \NR + \NC RS \NC right skip \NC \NR + \NC SP \NC space skip \NC \NR + \NC XS \NC x space skip \NC \NR + \NC ZS \NC zero space skip \NC \NR + \NC PF \NC par fill skip \NC \NR + \NC IN \NC indent skip \NC \NR + \NC CS \NC correction skip \NC \NR + \NC VS \NC vertical user skip \NC \NR + \NC HS \NC horizontal user skip \NC \NR + \NC IC \NC italic correcection \NC \NR + \TB + \NC NL \NC leaders \NC \NR + \NC CL \NC c leaders \NC \NR + \NC XL \NC x leaders \NC \NR + \NC GL \NC g leaders \NC \NR + \TB + \NC M:B \NC math begin \NC \NR + \NC M:E \NC math end \NC \NR + \NC W:* \NC whatsit \NC \NR + \stoptabulate + \stopboxedcolumns + \egroup + \endgroup +\stoptexdefinition + +\stopmodule + +\continueifinputfile{s-system-visual.mkiv} + +\usemodule[article-basic] + +\startTEXpage[width=20cm,offset=5mm] + + \visuallegend + +\stopTEXpage diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 1891e73c6..050fb0bd3 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 : 2020-07-13 23:44 +-- merge date : 2020-07-20 10:40 do -- begin closure to overcome local limits and interference @@ -9229,6 +9229,14 @@ function constructors.scale(tfmdata,specification) targetparameters.x_height=targetx_height targetparameters.quad=targetquad targetparameters.extra_space=targetextra_space + local hshift=parameters.hshift + if hshift then + targetparameters.hshift=delta*hshift + end + local vshift=parameters.vshift + if vshift then + targetparameters.vshift=delta*vshift + end local ascender=parameters.ascender if ascender then targetparameters.ascender=delta*ascender @@ -12712,6 +12720,7 @@ function readers.loadfont(filename,n,instance) hascolor=fontdata.hascolor or false, instance=fontdata.instance, factors=fontdata.factors, + nofsubfonts=fontdata.subfonts and #fontdata.subfonts or nil, }, resources={ filename=filename, @@ -37105,6 +37114,7 @@ local function setmathcharacters(tfmdata,characters,mathparameters,dx,dy,squeeze end end end +local shiftmode=CONTEXTLMTXMODE>0 local function manipulateeffect(tfmdata) local effect=tfmdata.properties.effect if effect then @@ -37126,38 +37136,45 @@ local function manipulateeffect(tfmdata) local factor=(1+effect.factor)*factor local hfactor=(1+effect.hfactor)*hfactor local vfactor=(1+effect.vfactor)*vfactor - local vshift=vshift~=0 and upcommand[vshift] or false + if shiftmode then + parameters.hshift=hshift + parameters.vshift=vshift + else + vshift=vshift~=0 and upcommand[vshift] or false + hshift=rightcommand[hshift] + end for unicode,character in next,characters do local oldwidth=character.width local oldheight=character.height local olddepth=character.depth if oldwidth and oldwidth>0 then character.width=oldwidth+wdelta - local commands=character.commands - local hshift=rightcommand[hshift] - if vshift then - if commands then - prependcommands (commands, - hshift, - vshift - ) - else - character.commands={ - hshift, - vshift, - charcommand[unicode] - } - end - else - if commands then - prependcommands (commands, - hshift - ) + if not shiftmode then + local commands=character.commands + if vshift then + if commands then + prependcommands (commands, + hshift, + vshift + ) + else + character.commands={ + hshift, + vshift, + charcommand[unicode] + } + end else - character.commands={ - hshift, - charcommand[unicode] - } + if commands then + prependcommands (commands, + hshift + ) + else + character.commands={ + hshift, + charcommand[unicode] + } + end end end end -- cgit v1.2.3