diff options
Diffstat (limited to 'macros/luatex/generic/minim-pdf/minim-pdf.lua')
-rw-r--r-- | macros/luatex/generic/minim-pdf/minim-pdf.lua | 138 |
1 files changed, 66 insertions, 72 deletions
diff --git a/macros/luatex/generic/minim-pdf/minim-pdf.lua b/macros/luatex/generic/minim-pdf/minim-pdf.lua index 101a548e4b..9d824a829f 100644 --- a/macros/luatex/generic/minim-pdf/minim-pdf.lua +++ b/macros/luatex/generic/minim-pdf/minim-pdf.lua @@ -2,7 +2,6 @@ local M = { } local alloc = require('minim-alloc') local cb = require('minim-callbacks') -alloc.remember('minim-hooks') alloc.remember('minim-pdf') -- 1 helper functions @@ -32,25 +31,10 @@ local pdf_name = alloc.pdf_name local pdf_string = alloc.pdf_string local options_scanner = alloc.options_scanner --- is this table empty? -local function is_empty(t) - for _, _ in pairs(t or {}) do - return false - end - return true -end - --- has this table just one element? local function singleton(t) - local one = false - for _, _ in pairs(t) do - if one then - return false - else - one = true - end - end - return one + local v = next(t) + v = v and not next(t, v) + return v and true or false end -- in-depth node list traversal; returns current and parent node @@ -92,6 +76,7 @@ local structure = { { index = 1, struct = 'Document', children = { }, + level = 0, -- for debugging only } } -- the parent tree will be filled automatically and separately @@ -158,7 +143,7 @@ local structure_types = alloc.saved_table('structure types', { -- block level structure elements (BLSE) P = { type = 'block' }, H = { type = 'block' }, - H1 = { type = 'block' }, -- for nonhierarchical tagging (do not use?) + H1 = { type = 'block' }, -- for nonhierarchical tagging (do not use) H2 = { type = 'block' }, -- __________ „ __________ H3 = { type = 'block' }, -- __________ „ __________ H4 = { type = 'block' }, -- __________ „ __________ @@ -328,7 +313,8 @@ local function make_rolemap() return '' end -local function make_attributes(res, t) +local function make_attributes(t) + local res = { } -- is there just one attribute? local list = not singleton(t) if list then table.insert(res, '[') end @@ -340,6 +326,7 @@ local function make_attributes(res, t) table.insert(res, '>>') end if list then table.insert(res, ']') end + return table.concat(res, ' ') end local attribute_classes = alloc.saved_table('attribute classes') @@ -347,7 +334,7 @@ local function make_classmap() local classes = { } for c, as in pairs(attribute_classes) do insert_formatted(classes, '\n%s', pdf_name(c)) - make_attributes(classes, as) + table.insert(classes, make_attributes(as)) end if #classes > 0 then return '\n/ClassMap << ' .. table.concat(classes, ' ') .. ' >>' @@ -355,11 +342,59 @@ local function make_classmap() return '' end +local id_tree = { } + +local function write_structure_element(se) + local res = { '<<' } + insert_formatted(res, '/Type/StructElem /S%s /P %d 0 R', pdf_name(se.struct), se.parent.objnum) + if se.id then insert_formatted(res, '/ID %s', pdf_string(se.id)) end + if se.lang and se.lang ~= se.parent.lang then insert_formatted(res, '/Lang %s', pdf_string(se.lang)) end + if se.alt then insert_formatted(res, '/Alt %s', pdf_string(se.alt)) end + if se.actual then insert_formatted(res, '/ActualText %s', pdf_string(se.actual)) end + if se.title then insert_formatted(res, '/T %s', pdf_string(se.title)) end + if #se.children > 0 then insert_formatted(res, '\n/K %s', format_K_array(se)) end + if se.mainpage then insert_formatted(res, '/Pg %d 0 R', se.mainpage) end + if se.class then + table.insert(res, '/C') + if #se.class > 1 then table.insert(res, '[') end + for _, c in ipairs(se.class) do + insert_formatted(res, '%s', pdf_name(c)) + end + if #se.class > 1 then table.insert(res, ']') end + end + if se.ref then + table.insert(res, '/Ref') + table.insert(res, '[') + for _, c in ipairs(se.ref) do + local onum = id_tree[c] + if onum then + insert_formatted(res, '%d 0 R', onum) + else + alloc.err('Invalid structure element ID: %s', c) + end + end + table.insert(res, ']') + end + if next(se.attributes or {}) then + table.insert(res, '/A') + table.insert(res, make_attributes(se.attributes)) + end + if se.files then + table.insert(res, '/AF [') + for _, fs in ipairs(se.files) do + insert_formatted(res, '%d 0 R', fs) + end + table.insert(res, ']') + end + table.insert(res, '>>') + pdf.immediateobj(se.objnum, table.concat(res, ' ')) +end + local function write_structure() if #structure == 1 then return end -- reserve object numbers, prepare for writing - local root_obj, parent_tree_obj = pdf.reserveobj(), pdf.reserveobj() - local id_tree, id_tree_obj = { }, pdf.reserveobj() + local root_obj, parent_tree_obj, id_tree_obj = + pdf.reserveobj(), pdf.reserveobj(), pdf.reserveobj() structure[1].parent = { objnum = root_obj } for _, se in ipairs(structure) do if not se.hidden then @@ -383,49 +418,7 @@ local function write_structure() -- write structure elements for _, se in ipairs(structure) do if not se.hidden then - local res = { '<<' } - insert_formatted(res, '/Type/StructElem /S%s /P %d 0 R', pdf_name(se.struct), se.parent.objnum) - if se.id then insert_formatted(res, '/ID %s', pdf_string(se.id)) end - if se.lang and se.lang ~= se.parent.lang then insert_formatted(res, '/Lang %s', pdf_string(se.lang)) end - if se.alt then insert_formatted(res, '/Alt %s', pdf_string(se.alt)) end - if se.actual then insert_formatted(res, '/ActualText %s', pdf_string(se.actual)) end - if se.title then insert_formatted(res, '/T %s', pdf_string(se.title)) end - if #se.children > 0 then insert_formatted(res, '\n/K %s', format_K_array(se)) end - if se.mainpage then insert_formatted(res, '/Pg %d 0 R', se.mainpage) end - if se.class then - table.insert(res, '/C') - if #se.class > 1 then table.insert(res, '[') end - for _, c in ipairs(se.class) do - insert_formatted(res, '%s', pdf_name(c)) - end - if #se.class > 1 then table.insert(res, ']') end - end - if se.ref then - table.insert(res, '/Ref') - table.insert(res, '[') - for _, c in ipairs(se.ref) do - local onum = id_tree[c] - if onum then - insert_formatted(res, '%d 0 R', onum) - else - alloc.err('Invalid structure element ID: %s', c) - end - end - table.insert(res, ']') - end - if not is_empty(se.attributes) then - table.insert(res, '/A') - make_attributes(res, se.attributes) - end - if se.files then - table.insert(res, '/AF [') - for _, fs in ipairs(se.files) do - insert_formatted(res, '%d 0 R', fs) - end - table.insert(res, ']') - end - table.insert(res, '>>') - pdf.immediateobj(se.objnum, table.concat(res, ' ')) + write_structure_element(se) end end -- write the parent tree (a number tree) @@ -519,7 +512,6 @@ end local function get_ancestor_of_type(se, stype) while se and se.struct ~= stype do - if se.level == -1000 then return end se = se.parent end return se and se.parent @@ -527,7 +519,8 @@ end function M.close_structure_node(stype, raiseerror) local strict = tex.count['strictstructuretagging'] > 0 - local current, open = current_structure_element() + local current = current_structure_element() + local open if strict then open = current.struct == stype and current.parent else @@ -574,6 +567,7 @@ function M.open_structure_node(n) n.order = n.order or tex.getattribute(current_order) n.parent = (n.parent and structure[n.parent]) or determine_parent_node(current_structure_element(), n) + n.level = n.parent.level + 1 table.insert(structure, n) -- determine the proper language code if n.lang then @@ -664,7 +658,7 @@ local mcid_list, pageobj local function clear_page_tagging_parameters() mcid_list, pageobj = { }, nil - _open_mci_node_ = function (se_num, order) + _open_mci_node_ = function (se_num, order) --luacheck: ignore 111 pageobj = pageobj or pdf.getpageref(status.total_pages + 1) local se = structure[se_num] pdf.print(string.format('%s <</MCID %d>> BDC ', pdf_name(se.struct), #mcid_list)) @@ -854,7 +848,7 @@ end) local function scan_escaped_argument(chars_to_escape) local stored = { } - for char in string.utfvalues(chars_to_escape) do + for _, char in utf8.codes(chars_to_escape) do stored[char] = tex.getcatcode(char) tex.setcatcode(char, 12) end @@ -1060,7 +1054,7 @@ function M.mark_discretionaries(head, gc) if #actual == 0 and pre and pre.char and pre.char == 0x2D then actual = '' -- soft hyphen U+00AD elseif #actual > 0 then - actual = string.utfcharacter(table.unpack(actual)) + actual = utf8.char(table.unpack(actual)) else goto continue end |