summaryrefslogtreecommitdiff
path: root/src/luaotfload-auxiliary.lua
diff options
context:
space:
mode:
authorPhilipp Gesang <phg@phi-gamma.net>2016-04-27 23:06:27 +0200
committerPhilipp Gesang <phg@phi-gamma.net>2016-04-27 23:06:27 +0200
commit6c52ede0dc26bf697e5cf2732dffab7bb8191473 (patch)
treec2425e083e73387d69afa6d349a3a3b8f19fb091 /src/luaotfload-auxiliary.lua
parente739376d6f7f55a74ecd215f2bd3b54a30367875 (diff)
parent23ff1b009f3b4df6754848196d7556c11c323d83 (diff)
downloadluaotfload-6c52ede0dc26bf697e5cf2732dffab7bb8191473.tar.gz
Merge pull request #345 from phi-gamma/master
first batch of fixes
Diffstat (limited to 'src/luaotfload-auxiliary.lua')
-rw-r--r--src/luaotfload-auxiliary.lua265
1 files changed, 190 insertions, 75 deletions
diff --git a/src/luaotfload-auxiliary.lua b/src/luaotfload-auxiliary.lua
index 3d300e7..e544dd7 100644
--- a/src/luaotfload-auxiliary.lua
+++ b/src/luaotfload-auxiliary.lua
@@ -88,13 +88,12 @@ package.
--doc]]--
local set_sscale_dimens = function (fontdata)
- local mathconstants = fontdata.MathConstants
- local parameters = fontdata.parameters
- if mathconstants then
- parameters[10] = mathconstants.ScriptPercentScaleDown or 70
- parameters[11] = mathconstants.ScriptScriptPercentScaleDown or 50
- end
- return fontdata
+ local resources = fontdata.resources if not resources then return end
+ local mathconstants = resources.MathConstants if not mathconstants then return end
+ local parameters = fontdata.parameters if not parameters then return end
+ --- the default values below are complete crap
+ parameters [10] = mathconstants.ScriptPercentScaleDown or 70
+ parameters [11] = mathconstants.ScriptScriptPercentScaleDown or 50
end
luaotfload_callbacks [#luaotfload_callbacks + 1] = {
@@ -104,8 +103,8 @@ luaotfload_callbacks [#luaotfload_callbacks + 1] = {
--- fontobj -> int
local lookup_units = function (fontdata)
local metadata = fontdata.shared and fontdata.shared.rawdata.metadata
- if metadata and metadata.units_per_em then
- return metadata.units_per_em
+ if metadata and metadata.units then
+ return metadata.units
elseif fontdata.parameters and fontdata.parameters.units then
return fontdata.parameters.units
elseif fontdata.units then --- v1.x
@@ -122,9 +121,9 @@ local patch_cambria_domh = function (fontdata)
local mathconstants = fontdata.MathConstants
if mathconstants and fontdata.psname == "CambriaMath" then
--- my test Cambria has 2048
- local units_per_em = fontdata.units_per_em or lookup_units(fontdata)
- local sz = fontdata.parameters.size or fontdata.size
- local mh = 2800 / units_per_em * sz
+ local units = fontdata.units or lookup_units(fontdata)
+ local sz = fontdata.parameters.size or fontdata.size
+ local mh = 2800 / units * sz
if mathconstants.DisplayOperatorMinHeight < mh then
mathconstants.DisplayOperatorMinHeight = mh
end
@@ -177,40 +176,95 @@ Comment from fontspec:
--doc]]--
+local capheight_reference_chars = { "X", "M", "Ж", "ξ", }
+local capheight_reference_codepoints do
+ local utfbyte = unicode.utf8.byte
+ capheight_reference_codepoints = { }
+ for i = 1, #capheight_reference_chars do
+ local chr = capheight_reference_chars [i]
+ capheight_reference_codepoints [i] = utfbyte (chr)
+ end
+end
+
+local determine_capheight = function (fontdata)
+ local parameters = fontdata.parameters if not parameters then return false end
+ local characters = fontdata.characters if not characters then return false end
+ --- Pretty simplistic but it does return *some* value for most fonts;
+ --- we could also refine the approach to return some kind of average
+ --- of all capital letters or a user-provided subset.
+ for i = 1, #capheight_reference_codepoints do
+ local refcp = capheight_reference_codepoints [i]
+ local refchar = characters [refcp]
+ if refchar then
+ logreport ("both", 4, "aux",
+ "picked height of character ‘%s’ (U+%d) as \\fontdimen8 \z
+ candidate",
+ capheight_reference_chars [i], refcp)
+ return refchar.height
+ end
+ end
+ return false
+end
+
+local query_ascender = function (fontdata)
+ local parameters = fontdata.parameters if not parameters then return false end
+ local shared = fontdata.shared if not shared then return false end
+ local rawdata = shared.rawdata if not rawdata then return false end
+ local metadata = rawdata.metadata if not metadata then return false end
+ local ascender = parameters.ascender
+ or metadata.ascender if not ascender then return false end
+ local units = metadata.units if units == 0 then return false end
+ local size = parameters.size if not size then return false end
+ return ascender * size / units
+end
+
+local query_capheight = function (fontdata)
+ local parameters = fontdata.parameters if not parameters then return false end
+ local shared = fontdata.shared if not shared then return false end
+ local rawdata = shared.rawdata if not rawdata then return false end
+ local metadata = rawdata.metadata if not metadata then return false end
+ local capheight = metadata.capheight if not capheight then return false end
+ local units = metadata.units if units == 0 then return false end
+ local size = parameters.size if not size then return false end
+ return capheight * size / units
+end
+
+local query_fontdimen8 = function (fontdata)
+ local parameters = fontdata.parameters if not parameters then return false end
+ local fontdimen8 = parameters [8]
+ if fontdimen8 then return fontdimen8 end
+ return false
+end
+
+local caphtfmt = function (ref, ht)
+ if not ht then return "<none>" end
+ if not ref then return tostring (ht) end
+ return stringformat ("%s(δ=%s)", ht, ht - ref)
+end
+
local set_capheight = function (fontdata)
- local shared = fontdata.shared
- local parameters = fontdata.parameters
- local capheight
- if shared
- and shared.rawdata.metadata
- and shared.rawdata.metadata.pfminfo
- then
- local units_per_em = parameters.units
- local size = parameters.size
- local os2_capheight = shared.rawdata.metadata.pfminfo.os2_capheight
-
- if capheight and os2_capheight > 0 then
- capheight = os2_capheight / units_per_em * size
- else
- local X8_str = stringbyte"X"
- local X8_chr = fontdata.characters[X8_str]
- if X8_chr then
- capheight = X8_chr.height
- else
- capheight = parameters.ascender / units_per_em * size
- end
- end
- else
- local X8_str = stringbyte "X"
- local X8_chr = fontdata.characters[X8_str]
- if X8_chr then
- capheight = X8_chr.height
- end
+ if not fontdata then
+ logreport ("both", 0, "aux",
+ "error: set_capheight() received garbage")
+ return
+ end
+ local capheight_dimen8 = query_fontdimen8 (fontdata)
+ local capheight_alleged = query_capheight (fontdata)
+ local capheight_ascender = query_ascender (fontdata)
+ local capheight_measured = determine_capheight (fontdata)
+ logreport ("term", 4, "aux",
+ "capht: param[8]=%s advertised=%s ascender=%s measured=%s",
+ tostring (capheight_dimen8),
+ caphtfmt (capheight_dimen8, capheight_alleged),
+ caphtfmt (capheight_dimen8, capheight_ascender),
+ caphtfmt (capheight_dimen8, capheight_measured))
+ if capheight_dimen8 then --- nothing to do
+ return
end
+
+ local capheight = capheight_alleged or capheight_ascender or capheight_measured
if capheight then
- --- is this legit? afaics there’s nothing else on the
- --- array part of that table
- fontdata.parameters[8] = capheight
+ fontdata.parameters [8] = capheight
end
end
@@ -263,20 +317,27 @@ end
--- int -> string -> bool -> (int | false)
local slot_of_name = function (font_id, glyphname, unsafe)
- local fontdata = identifiers[font_id]
- if fontdata then
- local unicode = fontdata.resources.unicodes[glyphname]
- if unicode then
- if type(unicode) == "number" then
- return unicode
- else
- return unicode[1] --- for multiple components
- end
--- else
--- --- missing
+ if not font_id or type (font_id) ~= "number"
+ or not glyphname or type (glyphname) ~= "string"
+ then
+ logreport ("both", 0, "aux",
+ "invalid parameters to slot_of_name (%s, %s)",
+ tostring (font_id), tostring (glyphname))
+ return false
+ end
+
+ local tfmdata = identifiers [font_id]
+ if not tfmdata then return raw_slot_of_name (font_id, glyphname) end
+ local resources = tfmdata.resources if not resources then return false end
+ local unicodes = resources.unicodes if not unicodes then return false end
+
+ local unicode = unicodes [glyphname]
+ if unicode then
+ if type (unicode) == "number" then
+ return unicode
+ else
+ return unicode [1] --- for multiple components
end
- elseif unsafe == true then -- for Robert
- return raw_slot_of_name(font_id, glyphname)
end
return false
end
@@ -298,11 +359,23 @@ local indices
--- int -> (string | false)
local name_of_slot = function (codepoint)
+ if not codepoint or type (codepoint) ~= "number" then
+ logreport ("both", 0, "aux",
+ "invalid parameters to name_of_slot (%s)",
+ tostring (codepoint))
+ return false
+ end
+
if not indices then --- this will load the glyph list
local unicodes = encodings.agl.unicodes
- indices = table.swapped(unicodes)
+ if not unicodes or not next (unicodes)then
+ logreport ("both", 0, "aux",
+ "name_of_slot: failed to load the AGL.")
+ end
+ indices = table.swapped (unicodes)
end
- local glyphname = indices[codepoint]
+
+ local glyphname = indices [codepoint]
if glyphname then
return glyphname
end
@@ -317,6 +390,12 @@ aux.name_of_slot = name_of_slot
-----------------------------------------------------------------------
--- lots of arrowcode ahead
+local get_features = function (tfmdata)
+ local resources = tfmdata.resources if not resources then return false end
+ local features = resources.features if not features then return false end
+ return features
+end
+
--[[doc--
This function, modeled after “check_script()” from fontspec, returns
true if in the given font, the script “asked_script” is accounted for in at
@@ -325,13 +404,23 @@ least one feature.
--- int -> string -> bool
local provides_script = function (font_id, asked_script)
+ if not font_id or type (font_id) ~= "number"
+ or not asked_script or type (asked_script) ~= "string"
+ then
+ logreport ("both", 0, "aux",
+ "invalid parameters to provides_script(%s, %s)",
+ tostring (font_id), tostring (asked_script))
+ return false
+ end
asked_script = stringlower(asked_script)
if font_id and font_id > 0 then
- local tfmdata = identifiers[font_id] if not tfmdata then return false end
- local shared = tfmdata.shared if not shared then return false end
- local fontdata = shared.rawdata if not fontdata then return false end
- local fontname = fontdata.metadata.fontname
- local features = fontdata.resources.features
+ local tfmdata = identifiers[font_id]
+ if not tfmdata then return false end
+ local features = get_features (tfmdata)
+ if features == false then
+ logreport ("log", 1, "aux", "font no %d lacks a features table", font_id)
+ return false
+ end
for method, featuredata in next, features do
--- where method: "gpos" | "gsub"
for feature, data in next, featuredata do
@@ -362,14 +451,27 @@ feature.
--- int -> string -> string -> bool
local provides_language = function (font_id, asked_script, asked_language)
- asked_script = stringlower(asked_script)
- asked_language = stringlower(asked_language)
+ if not font_id or type (font_id) ~= "number"
+ or not asked_script or type (asked_script) ~= "string"
+ or not asked_language or type (asked_language) ~= "string"
+ then
+ logreport ("both", 0, "aux",
+ "invalid parameters to provides_language(%s, %s, %s)",
+ tostring (font_id),
+ tostring (asked_script),
+ tostring (asked_language))
+ return false
+ end
+ asked_script = stringlower(asked_script)
+ asked_language = stringlower(asked_language)
if font_id and font_id > 0 then
- local tfmdata = identifiers[font_id] if not tfmdata then return false end
- local shared = tfmdata.shared if not shared then return false end
- local fontdata = shared.rawdata if not fontdata then return false end
- local fontname = fontdata.metadata.fontname
- local features = fontdata.resources.features
+ local tfmdata = identifiers[font_id]
+ if not tfmdata then return false end
+ local features = get_features (tfmdata)
+ if features == false then
+ logreport ("log", 1, "aux", "font no %d lacks a features table", font_id)
+ return false
+ end
for method, featuredata in next, features do
--- where method: "gpos" | "gsub"
for feature, data in next, featuredata do
@@ -432,16 +534,29 @@ accounted for in the script with tag “asked_script” in feature
--- int -> string -> string -> string -> bool
local provides_feature = function (font_id, asked_script,
asked_language, asked_feature)
+ if not font_id or type (font_id) ~= "number"
+ or not asked_script or type (asked_script) ~= "string"
+ or not asked_language or type (asked_language) ~= "string"
+ or not asked_feature or type (asked_feature) ~= "string"
+ then
+ logreport ("both", 0, "aux",
+ "invalid parameters to provides_feature(%s, %s, %s, %s)",
+ tostring (font_id), tostring (asked_script),
+ tostring (asked_language), tostring (asked_feature))
+ return false
+ end
asked_script = stringlower(asked_script)
asked_language = stringlower(asked_language)
asked_feature = lpegmatch(strip_garbage, asked_feature)
if font_id and font_id > 0 then
- local tfmdata = identifiers[font_id] if not tfmdata then return false end
- local shared = tfmdata.shared if not shared then return false end
- local fontdata = shared.rawdata if not fontdata then return false end
- local features = fontdata.resources.features
- local fontname = fontdata.metadata.fontname
+ local tfmdata = identifiers[font_id]
+ if not tfmdata then return false end
+ local features = get_features (tfmdata)
+ if features == false then
+ logreport ("log", 1, "aux", "font no %d lacks a features table", font_id)
+ return false
+ end
for method, featuredata in next, features do
--- where method: "gpos" | "gsub"
local feature = featuredata[asked_feature]