summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/l-dimen.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/l-dimen.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/l-dimen.lua109
1 files changed, 86 insertions, 23 deletions
diff --git a/Master/texmf-dist/tex/context/base/l-dimen.lua b/Master/texmf-dist/tex/context/base/l-dimen.lua
index 32becb2768e..da5ab143e58 100644
--- a/Master/texmf-dist/tex/context/base/l-dimen.lua
+++ b/Master/texmf-dist/tex/context/base/l-dimen.lua
@@ -15,14 +15,20 @@ done by using the conversion factors collected in the following
table.</p>
--ldx]]--
-local format, type = string.format, type
+local format, match, gsub, type, setmetatable = string.format, string.match, string.gsub, type, setmetatable
+local P, S, R, Cc, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.match
+
+number = number or { }
+
+number.tonumberf = function(n) return match(format("%.20f",n),"(.-0?)0*$") end -- one zero too much but alas
+number.tonumberg = function(n) return format("%.20g",n) end
local dimenfactors = {
["pt"] = 1/65536,
["in"] = ( 100/ 7227)/65536,
["cm"] = ( 254/ 7227)/65536,
- ["mm"] = ( 254/72270)/65536,
- ["sp"] = 1,
+ ["mm"] = ( 2540/ 7227)/65536,
+ ["sp"] = 1, -- 65536 sp in 1pt
["bp"] = ( 7200/ 7227)/65536,
["pc"] = ( 1/ 12)/65536,
["dd"] = ( 1157/ 1238)/65536,
@@ -31,17 +37,62 @@ local dimenfactors = {
["nc"] = ( 5080/65043)/65536
}
+--~ print(table.serialize(dimenfactors))
+--~
+--~ %.99g:
+--~
+--~ t={
+--~ ["bp"]=1.5201782378580324e-005,
+--~ ["cc"]=1.1883696112892098e-006,
+--~ ["cm"]=5.3628510057769479e-007,
+--~ ["dd"]=1.4260435335470516e-005,
+--~ ["em"]=0.000152587890625,
+--~ ["ex"]=6.103515625e-005,
+--~ ["in"]=2.1113586636917117e-007,
+--~ ["mm"]=5.3628510057769473e-008,
+--~ ["nc"]=1.1917446679504327e-006,
+--~ ["nd"]=1.4300936015405194e-005,
+--~ ["pc"]=1.2715657552083333e-006,
+--~ ["pt"]=1.52587890625e-005,
+--~ ["sp"]=1,
+--~ }
+--~
+--~ patched %s and tonumber
+--~
+--~ t={
+--~ ["bp"]=0.00001520178238,
+--~ ["cc"]=0.00000118836961,
+--~ ["cm"]=0.0000005362851,
+--~ ["dd"]=0.00001426043534,
+--~ ["em"]=0.00015258789063,
+--~ ["ex"]=0.00006103515625,
+--~ ["in"]=0.00000021113587,
+--~ ["mm"]=0.00000005362851,
+--~ ["nc"]=0.00000119174467,
+--~ ["nd"]=0.00001430093602,
+--~ ["pc"]=0.00000127156576,
+--~ ["pt"]=0.00001525878906,
+--~ ["sp"]=1,
+--~ }
+
--[[ldx--
<p>A conversion function that takes a number, unit (string) and optional
format (string) is implemented using this table.</p>
--ldx]]--
+-- was:
+
local function todimen(n,unit,fmt)
if type(n) == 'string' then
return n
else
unit = unit or 'pt'
- return format(fmt or "%.5f%s",n*dimenfactors[unit],unit)
+ return format(fmt or "%s%s",n*dimenfactors[unit],unit)
+ -- if fmt then
+ -- return format(fmt,n*dimenfactors[unit],unit)
+ -- else
+ -- return match(format("%.20f",n*dimenfactors[unit]),"(.-0?)0*$") .. unit
+ -- end
end
end
@@ -49,8 +100,7 @@ end
<p>We collect a bunch of converters in the <type>number</type> namespace.</p>
--ldx]]--
-number = number or { }
-
+number.maxdimen = 1073741823
number.todimen = todimen
number.dimenfactors = dimenfactors
@@ -75,10 +125,12 @@ a number and optionally a unit. When no unit is given a constant
capture takes place.</p>
--ldx]]--
-local amount = (lpeg.S("+-")^0 * lpeg.R("09")^0 * lpeg.P(".")^0 * lpeg.R("09")^0) + lpeg.Cc("0")
-local unit = lpeg.R("az")^1
+local amount = (S("+-")^0 * R("09")^0 * P(".")^0 * R("09")^0) + Cc("0")
+local unit = R("az")^1
-local pattern = amount/tonumber * (unit^1/dimenfactors + lpeg.Cc(1)) -- tonumber is new
+local dimenpair = amount/tonumber * (unit^1/dimenfactors + Cc(1)) -- tonumber is new
+
+lpeg.patterns.dimenpair = dimenpair
--[[ldx--
<p>We use a metatable to intercept errors. When no key is found in
@@ -89,30 +141,37 @@ alternative index function.</p>
local mt = { } setmetatable(dimenfactors,mt)
mt.__index = function(t,s)
- error("wrong dimension: " .. s)
- return 1
+ -- error("wrong dimension: " .. (s or "?")) -- better a message
+ return false
end
function string:todimen()
if type(self) == "number" then
return self
else
- local value, unit = pattern:match(self)
- print(value,unit)
+ local value, unit = lpegmatch(dimenpair,self)
return value/unit
end
end
+local amount = S("+-")^0 * R("09")^0 * S(".,")^0 * R("09")^0
+local unit = P("pt") + P("cm") + P("mm") + P("sp") + P("bp") + P("in") +
+ P("pc") + P("dd") + P("cc") + P("nd") + P("nc")
+
+local validdimen = amount * unit
+
+lpeg.patterns.validdimen = pattern
+
--[[ldx--
<p>This converter accepts calls like:</p>
<typing>
-string.todimen("10"))
-string.todimen(".10"))
-string.todimen("10.0"))
-string.todimen("10.0pt"))
-string.todimen("10pt"))
-string.todimen("10.0pt"))
+string.todimen("10")
+string.todimen(".10")
+string.todimen("10.0")
+string.todimen("10.0pt")
+string.todimen("10pt")
+string.todimen("10.0pt")
</typing>
<p>And of course the often more efficient:</p>
@@ -145,7 +204,7 @@ function dimen(a)
if a then
local ta= type(a)
if ta == "string" then
- local value, unit = pattern:match(a)
+ local value, unit = lpegmatch(pattern,a)
if type(unit) == "function" then
k = value/unit()
else
@@ -262,7 +321,7 @@ is loaded, the relevant tables that hold the functions needed may not
yet be available.</p>
--ldx]]--
-function dimensions.texify()
+function dimensions.texify() -- todo: %
local fti, fc = fonts and fonts.ids and fonts.ids, font and font.current
if fti and fc then
dimenfactors["ex"] = function() return fti[fc()].ex_height end
@@ -312,7 +371,7 @@ function dimen(a)
if k then
a = k
else
- local value, unit = pattern:match(a)
+ local value, unit = lpegmatch(dimenpair,a)
if type(unit) == "function" then
k = value/unit()
else
@@ -336,7 +395,7 @@ function string:todimen()
else
local k = known[self]
if not k then
- local value, unit = pattern:match(self)
+ local value, unit = lpegmatch(dimenpair,self)
if value and unit then
k = value/unit
else
@@ -349,6 +408,10 @@ function string:todimen()
end
end
+function number.toscaled(d)
+ return format("0.5f",d/2^16)
+end
+
--[[ldx--
<p>In a similar fashion we can define a glue datatype. In that case we
probably use a hash instead of a one-element table.</p>