summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/tagpdf/tagpdf-backend.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/tagpdf/tagpdf-backend.dtx')
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-backend.dtx1059
1 files changed, 693 insertions, 366 deletions
diff --git a/macros/latex/contrib/tagpdf/tagpdf-backend.dtx b/macros/latex/contrib/tagpdf/tagpdf-backend.dtx
index 1010c79b7a..f643e3dbde 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-backend.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-backend.dtx
@@ -22,31 +22,57 @@
%
% for those people who are interested.
%
+%<*driver>
+\RequirePackage{pdfmanagement-testphase}
+\DeclareDocumentMetadata{}
+\makeatletter
+\declare@file@substitution{doc.sty}{doc-v3beta.sty}
+\makeatother
+\documentclass{l3doc}
+\usepackage{array,booktabs,caption}
+\hypersetup{pdfauthor=Ulrike Fischer,
+ pdftitle=tagpdf-mc module (tagpdf)}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
% \fi
+% \title{^^A
+% The \pkg{tagpdf-luatex.def} \\ Driver for luatex ^^A
+% \\ Part of the tagpdf package
+% }
%
+% \author{^^A
+% Ulrike Fischer\thanks
+% {^^A
+% E-mail:
+% \href{mailto:fischer@troubleshooting-tex.de}
+% {fischer@troubleshooting-tex.de}^^A
+% }^^A
+% }
+%
+% \date{Version 0.9, released 2021-06-29}
+% \maketitle
+% \begin{implementation}
% \begin{macrocode}
%<@@=tag>
%<*luatex>
-\ProvidesExplFile {tagpdf-luatex.def} {2021-06-14} {0.82}
+\ProvidesExplFile {tagpdf-luatex.def} {2021-06-29} {0.9}
{tagpdf~driver~for~luatex}
-
-\newattribute \l_@@_mc_type_attr %the value represent the type
-\newattribute \l_@@_mc_cnt_attr %will hold the \c@g_@@_MCID_abs_int value
-
-\newattribute \g_@@_interwordspace_attr
-\newattribute \g_@@_interwordfont_attr
-
-% The lua code
-% ensure that 10pt font has been loaded:
+% \end{macrocode}
+% \section{Loading the lua}
+% The space code requires that the fall back font has been loaded and initialized,
+% so we force that first. But perhaps this could be done in the kernel.
+%
+% \begin{macrocode}
{
\fontencoding{TU}\fontfamily{lmr}\fontseries{m}\fontshape{n}\fontsize{10pt}{10pt}\selectfont
}
-\directlua { tagpdf=require('tagpdf.lua') }
-
-%%%% driver (lualatex) commands
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
+\lua_now:e { tagpdf=require('tagpdf.lua') }
+% \end{macrocode}
+%
+% The following defines wrappers around prop and seq commands to store the
+% data also in lua tables.
% I probably want also lua tables
% I put them in the ltx.@@.tables namespaces
% The tables will be named like the variables but without backslash
@@ -54,94 +80,80 @@
% ltx.@@.tables[string]
% Old code, I'm not quite sure if this was a good idea. Now I have mix of table in
% ltx.@@.tables and ltx.@@.mc/struct. And a lot is probably not needed.
-
-
-\cs_new_protected:Nn \@@_prop_new:N
+% TODO: this should be cleaned up, but at least roles are currently using
+% the table!
+%
+% \begin{macro}
+% {
+% \@@_prop_new:N,
+% \@@_seq_new:N,
+% \@@_prop_gput:Nnn,
+% \@@_seq_gput_right:Nn,
+% \@@_seq_item:cn,
+% \@@_prop_item:cn,
+% \@@_seq_show:N,
+% \@@_prop_show:N
+% }
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_prop_new:N #1
{
\prop_new:N #1
- \directlua { ltx.@@.tables.\cs_to_str:N#1 = {} }
+ \lua_now:e { ltx.@@.tables.\cs_to_str:N#1 = {} }
}
-\cs_new_protected:Nn \@@_seq_new:N
+\cs_set_protected:Npn \@@_seq_new:N #1
{
\seq_new:N #1
- \directlua { ltx.@@.tables.\cs_to_str:N#1 = {} }
+ \lua_now:e { ltx.@@.tables.\cs_to_str:N#1 = {} }
}
-\cs_new_protected:Nn \@@_prop_gput:Nnn
+\cs_set_protected:Npn \@@_prop_gput:Nnn #1 #2 #3
{
\prop_gput:Nnn #1 { #2 } { #3 }
- \directlua { ltx.@@.tables.\cs_to_str:N#1 ["#2"] = "#3" }
+ \lua_now:e { ltx.@@.tables.\cs_to_str:N#1 ["#2"] = "#3" }
}
-\cs_new_protected:Nn \@@_seq_gput_right:Nn
+\cs_set_protected:Npn \@@_seq_gput_right:Nn #1 #2
{
\seq_gput_right:Nn #1 { #2 }
- \directlua { table.insert(ltx.@@.tables.\cs_to_str:N#1, "#2") }
+ \lua_now:e { table.insert(ltx.@@.tables.\cs_to_str:N#1, "#2") }
}
%Hm not quite sure about the naming
-\cs_new:Npn \@@_seq_item:cn #1 #2
+\cs_set:Npn \@@_seq_item:cn #1 #2
{
- \directlua { tex.print(ltx.@@.tables.#1[#2]) }
+ \lua_now:e { tex.print(ltx.@@.tables.#1[#2]) }
}
-\cs_new:Npn \@@_prop_item:cn #1 #2
+\cs_set:Npn \@@_prop_item:cn #1 #2
{
- \directlua { tex.print(ltx.@@.tables.#1["#2"]) }
+ \lua_now:e { tex.print(ltx.@@.tables.#1["#2"]) }
}
%for debugging commands that show both the seq/prop and the lua tables
-\cs_new_protected:Nn \@@_seq_show:N
+\cs_set_protected:Npn \@@_seq_show:N #1
{
\seq_show:N #1
- \directlua { ltx.@@.trace.log ("lua~sequence~array~\cs_to_str:N#1",1) }
- \directlua { ltx.@@.trace.show_seq (ltx.@@.tables.\cs_to_str:N#1) }
+ \lua_now:e { ltx.@@.trace.log ("lua~sequence~array~\cs_to_str:N#1",1) }
+ \lua_now:e { ltx.@@.trace.show_seq (ltx.@@.tables.\cs_to_str:N#1) }
}
-\cs_new_protected:Nn \@@_prop_show:N
+\cs_set_protected:Npn \@@_prop_show:N #1
{
\prop_show:N #1
- \directlua {ltx.@@.trace.log ("lua~property~table~\cs_to_str:N#1",1) }
- \directlua {ltx.@@.trace.show_prop (ltx.@@.tables.\cs_to_str:N#1) }
+ \lua_now:e {ltx.@@.trace.log ("lua~property~table~\cs_to_str:N#1",1) }
+ \lua_now:e {ltx.@@.trace.show_prop (ltx.@@.tables.\cs_to_str:N#1) }
}
-%</luatex>
% \end{macrocode}
-%
+% \end{macro}
% \begin{macrocode}
-%<*pdftex>
-\ProvidesExplFile {tagpdf-pdftex.def} {2021-06-14} {0.82}
- {tagpdf~driver~for~pdftex}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%%% driver (pdflatex) commands
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-% These commands are only aliases for pdflatex but are defined differently with luatex
-% to get also lua tables.
-\cs_set_eq:NN \@@_prop_new:N \prop_new:N
-
-\cs_set_eq:NN \@@_seq_new:N \seq_new:N
-
-\cs_set_eq:NN \@@_prop_gput:Nnn \prop_gput:Nnn
-
-\cs_set_eq:NN \@@_seq_gput_right:Nn \seq_gput_right:Nn
-
-\cs_set_eq:NN \@@_seq_item:cn \seq_item:cn
-
-\cs_set_eq:NN \@@_prop_item:cn \prop_item:cn
-
-\cs_set_eq:NN \@@_seq_show:N \seq_show:N
-
-\cs_set_eq:NN \@@_prop_show:N \prop_show:N
-
-%</pdftex>
+%</luatex>
% \end{macrocode}
+% The module declaration
% \begin{macrocode}
%<*lua>
-- tagpdf.lua
@@ -149,8 +161,8 @@
local ProvidesLuaModule = {
name = "tagpdf",
- version = "0.82", --TAGVERSION
- date = "2021-06-14", --TAGDATE
+ version = "0.9", --TAGVERSION
+ date = "2021-06-29", --TAGDATE
description = "tagpdf lua code",
license = "The LATEX Project Public License 1.3c"
}
@@ -168,8 +180,9 @@ The code has quite probably a number of problems
-
--]]
-
-
+% \end{macrocode}
+% Some comments about the lua structure.
+% \begin{macrocode}
--[[
the main table is named ltx.@@. It contains the functions and also the data
collected during the compilation.
@@ -199,9 +212,10 @@ functions
ltx.@@.func.mark_shipout (): a wrapper around the core function which inserts the last EMC
ltx.@@.func.fill_parent_tree_line (page): outputs the entries of the parenttree for this page
ltx.@@.func.output_parenttree(): outputs the content of the parenttree
+ ltx.@@.func.pdf_object_ref(name): outputs the object reference for the object name
ltx.@@.func.markspaceon(), ltx.@@.func.markspaceoff(): (de)activates the marking of positions for space chars
- ltx.@@.trace.show_mc_data (num): shows ltx.@@.mc[num]
- ltx.@@.trace.show_all_mc_data (max): shows a maximum about mc's
+ ltx.@@.trace.show_mc_data (num,loglevel): shows ltx.@@.mc[num] is the current log level is >= loglevel
+ ltx.@@.trace.show_all_mc_data (max,loglevel): shows a maximum about mc's if the current log level is >= loglevel
ltx.@@.trace.show_seq: shows a sequence (array)
ltx.@@.trace.show_struct_data (num): shows data of structure num
ltx.@@.trace.show_prop: shows a prop
@@ -209,19 +223,34 @@ functions
ltx.@@.trace.showspaces : boolean
--]]
-local mctypeattributeid = luatexbase.registernumber ("l_@@_mc_type_attr")
-local mccntattributeid = luatexbase.registernumber ("l_@@_mc_cnt_attr")
-local iwspaceattributeid = luatexbase.registernumber ("g_@@_interwordspace_attr")
-local iwfontattributeid = luatexbase.registernumber ("g_@@_interwordfont_attr")
-
-
-local catlatex = luatexbase.registernumber("catcodetable@latex")
+% \end{macrocode}
+% This set-ups the main attribute registers.
+% The mc_type attribute stores the type (P, Span etc) encoded as a num,
+% The mc_cnt attribute stores the absolute number and allows so to see
+% if a node belongs to the same mc-chunk.
+%
+% The interwordspace attr is set by the function |@@_mark_spaces|, and marks
+% the place where spaces should be inserted.
+% The interwordfont attr is set by the function |@@_mark_spaces| too and
+% stores the font, so that we can decide which font
+% to use for the real space char.
+% \begin{macrocode}
+local mctypeattributeid = luatexbase.new_attribute ("g_@@_mc_type_attr")
+local mccntattributeid = luatexbase.new_attribute ("g_@@_mc_cnt_attr")
+local iwspaceattributeid = luatexbase.new_attribute ("g_@@_interwordspace_attr")
+local iwfontattributeid = luatexbase.new_attribute ("g_@@_interwordfont_attr")
+% \end{macrocode}
+% with this token we can query the state of the boolean
+% and so detect if unmarked nodes should be marked as attributes
+% \begin{macrocode}
local tagunmarkedbool= token.create("g_@@_tagunmarked_bool")
local truebool = token.create("c_true_bool")
-
+% \end{macrocode}
+% Now a number of local versions from global tables.
+% Not all is perhaps needed, most node variants were copied from lua-debug.
+% \begin{macrocode}
+local catlatex = luatexbase.registernumber("catcodetable@latex")
local tableinsert = table.insert
-
--- not all needed, copied from lua-visual-debug.
local nodeid = node.id
local nodecopy = node.copy
local nodegetattribute = node.get_attribute
@@ -247,29 +276,29 @@ local KERN = node.id("kern")
local PENALTY = node.id("penalty")
local LOCAL_PAR = node.id("local_par")
local MATH = node.id("math")
-
-local function @@_get_mathsubtype (mathnode)
- if mathnode.subtype == 0 then
- subtype = "beginmath"
- else
- subtype = "endmath"
- end
- return subtype
-end
-
-
-
+% \end{macrocode}
+% Now we setup the main table structure. ltx is used by other latex code too!
+% \begin{macrocode}
ltx = ltx or { }
ltx.@@ = ltx.@@ or { }
-ltx.@@.mc = ltx.@@.mc or { } -- mc data
-ltx.@@.struct = ltx.@@.struct or { } -- struct data
-ltx.@@.tables = ltx.@@.tables or { } -- tables created with new prop and new seq.
- -- wasn't a so great idea ...
-ltx.@@.page = ltx.@@.page or { } -- page data, currently only i->{0->mcnum,1->mcnum,...}
-ltx.@@.trace = ltx.@@.trace or { } -- show commands
-ltx.@@.func = ltx.@@.func or { } -- functions
-ltx.@@.conf = ltx.@@.conf or { } -- configuration variables
-
+ltx.@@.mc = ltx.@@.mc or { } -- mc data
+ltx.@@.struct = ltx.@@.struct or { } -- struct data
+ltx.@@.tables = ltx.@@.tables or { } -- tables created with new prop and new seq.
+ -- wasn't a so great idea ...
+ -- g_@@_role_tags_seq used by tag<-> is in this tables!
+ltx.@@.page = ltx.@@.page or { } -- page data, currently only i->{0->mcnum,1->mcnum,...}
+ltx.@@.trace = ltx.@@.trace or { } -- show commands
+ltx.@@.func = ltx.@@.func or { } -- functions
+ltx.@@.conf = ltx.@@.conf or { } -- configuration variables
+% \end{macrocode}
+% \section{Logging functions}
+%
+% \begin{macro}{@@_log,ltx.@@.trace.log}
+% This rather simple log function takes as argument a
+% message (string) and a number and
+% will output the message to the log/terminal if the current loglevel
+% is greater or equal than num.
+% \begin{macrocode}
local @@_log =
function (message,loglevel)
if (loglevel or 3) <= tex.count["l_@@_loglevel_int"] then
@@ -278,16 +307,267 @@ local @@_log =
end
ltx.@@.trace.log = @@_log
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{ltx.@@.trace.show_seq}
+% This shows the content of a seq as stored in the tables table.
+% It is used by the |\@@_seq_show:N| function. It is not used
+% in user commands, only for debugging, and so requires log level >0.
+% \begin{macrocode}
+function ltx.@@.trace.show_seq (seq)
+ if (type(seq) == "table") then
+ for i,v in ipairs(seq) do
+ @@_log ("[" .. i .. "] => " .. tostring(v),1)
+ end
+ else
+ @@_log ("sequence " .. tostring(seq) .. " not found",1)
+ end
+end
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{ @@_pairs_prop,ltx.@@.trace.show_prop}
+% This shows the content of a prop as stored in the tables table.
+% It is used by the |\@@_prop_show:N| function.
+% \begin{macrocode}
+local @@_pairs_prop =
+ function (prop)
+ local a = {}
+ for n in pairs(prop) do tableinsert(a, n) end
+ table.sort(a)
+ local i = 0 -- iterator variable
+ local iter = function () -- iterator function
+ i = i + 1
+ if a[i] == nil then return nil
+ else return a[i], prop[a[i]]
+ end
+ end
+ return iter
+ end
+function ltx.@@.trace.show_prop (prop)
+ if (type(prop) == "table") then
+ for i,v in @@_pairs_prop (prop) do
+ @@_log ("[" .. i .. "] => " .. tostring(v),1)
+ end
+ else
+ @@_log ("prop " .. tostring(prop) .. " not found or not a table",1)
+ end
+ end
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{ltx.@@.trace.show_mc_data}
+% This shows some data for a mc given by |num|.
+% If something is shown depends on the log level.
+% The function is used by the following function and then in
+% |\ShowTagging|
+% \begin{macrocode}
+function ltx.@@.trace.show_mc_data (num,loglevel)
+ if ltx.@@ and ltx.@@.mc and ltx.@@.mc[num] then
+ for k,v in pairs(ltx.@@.mc[num]) do
+ @@_log ("mc"..num..": "..tostring(k).."=>"..tostring(v),loglevel)
+ end
+ if ltx.@@.mc[num]["kids"] then
+ @@_log ("mc" .. num .. " has " .. #ltx.@@.mc[num]["kids"] .. " kids",loglevel)
+ for k,v in ipairs(ltx.@@.mc[num]["kids"]) do
+ @@_log ("mc ".. num .. " kid "..k.." =>" .. v.kid.." on page " ..v.page,loglevel)
+ end
+ end
+ else
+ @@_log ("mc"..num.." not found",loglevel)
+ end
+end
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{ltx.@@.trace.show_all_mc_data}
+% This shows data for the mc's between |min| and |max| (numbers).
+% It is used by the |\ShowTagging| function.
+% \begin{macrocode}
+function ltx.@@.trace.show_all_mc_data (min,max,loglevel)
+ for i = min, max do
+ ltx.@@.trace.show_mc_data (i,loglevel)
+ end
+ texio.write_nl("")
+end
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}
+% {
+% ltx.@@.trace.show_struct_data
+% }
+% This function shows some struct data.
+% Unused but kept for debugging.
+% \begin{macrocode}
+function ltx.@@.trace.show_struct_data (num)
+ if ltx.@@ and ltx.@@.struct and ltx.@@.struct[num] then
+ for k,v in ipairs(ltx.@@.struct[num]) do
+ @@_log ("struct "..num..": "..tostring(k).."=>"..tostring(v),1)
+ end
+ else
+ @@_log ("struct "..num.." not found ",1)
+ end
+end
+% \end{macrocode}
+% \end{macro}
+
+%
+% \section{Helper functions}
+% \subsection{Retrieve data functions}
+% \begin{macro}{@@_get_mc_cnt_type_tag}
+% This takes a node as argument and returns the mc-cnt, the mc-type and
+% and the tag (calculated from the mc-cnt.
+% \begin{macrocode}
local @@_get_mc_cnt_type_tag = function (n)
local mccnt = nodegetattribute(n,mccntattributeid) or -1
local mctype = nodegetattribute(n,mctypeattributeid) or -1
local tag = ltx.@@.func.get_tag_from(mctype)
return mccnt,mctype,tag
end
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{@@_get_mathsubtype}
+% This function allows to detect if we are at the begin or the end of math.
+% It takes as argument a mathnode.
+% \begin{macrocode}
+local function @@_get_mathsubtype (mathnode)
+ if mathnode.subtype == 0 then
+ subtype = "beginmath"
+ else
+ subtype = "endmath"
+ end
+ return subtype
+end
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}
+% {
+% @@_get_num_from,
+% ltx.@@.func.get_num_from,
+% ltx.@@.func.output_num_from
+% }
+% These functions take as argument a string |tag|, and return the number
+% under which is it recorded (and so the attribute value).
+% The first function outputs the number for lua, while the |output| function
+% outputs to tex.
+% \begin{macrocode}
+local @@_get_num_from =
+ function (tag)
+ if ltx.@@.tables["g_@@_role_tags_prop"][tag] then
+ a= ltx.@@.tables["g_@@_role_tags_prop"][tag]
+ else
+ a= -1
+ end
+ return a
+ end
+
+ltx.@@.func.get_num_from = @@_get_num_from
+
+function ltx.@@.func.output_num_from (tag)
+ local num = @@_get_num_from (tag)
+ tex.sprint(catlatex,num)
+ if num == -1 then
+ @@_log ("Unknown tag "..tag.." used")
+ end
+end
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% @@_get_tag_from ,
+% ltx.@@.func.get_tag_from,
+% ltx.@@.func.output_tag_from
+% }
+% These functions are the opposites to the previous function:
+% they take as argument a number (the attribute value) and return the string |tag|.
+% The first function outputs the number for lua, while the |output| function
+% outputs to tex.
+% \begin{macrocode}
+local @@_get_tag_from =
+ function (num)
+ if ltx.@@.tables["g_@@_role_tags_seq"][num] then
+ a = ltx.@@.tables["g_@@_role_tags_seq"][num]
+ else
+ a= "UNKNOWN"
+ end
+ return a
+end
+ltx.@@.func.get_tag_from = @@_get_tag_from
+function ltx.@@.func.output_tag_from (num)
+ tex.sprint(catlatex,@@_get_tag_from (num))
+end
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}
+% {
+% ltx.@@.func.store_mc_data
+% }
+% This function stores for |key|=|data| for mc-chunk |num|. It is used in the
+% tagpdf-mc code, to store for example the tag string, and the raw options.
+% \begin{macrocode}
+function ltx.@@.func.store_mc_data (num,key,data)
+ ltx.@@.mc[num] = ltx.@@.mc[num] or { }
+ ltx.@@.mc[num][key] = data
+ @@_log ("INFO TEX-STORE-MC-DATA: "..num.." => "..tostring(key).." => "..tostring(data),3)
+end
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% ltx.@@.func.store_mc_label
+% }
+% This function stores the |label|=|num| relationship in the |labels| subtable.
+% TODO: this is probably unused and can go.
+% \begin{macrocode}
+function ltx.@@.func.store_mc_label (label,num)
+ ltx.@@.mc["labels"] = ltx.@@.mc["labels"] or { }
+ ltx.@@.mc.labels[label] = num
+end
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}
+% {
+% ltx.@@.func.store_mc_kid
+% }
+% This function is used in the traversing code. It stores
+% a sub-chunk of a mc |mcnum| into the |kids| table.
+% \begin{macrocode}
+function ltx.@@.func.store_mc_kid (mcnum,kid,page)
+ ltx.@@.trace.log("INFO TAG-STORE-MC-KID: "..mcnum.." => " .. kid.." on page " .. page,3)
+ ltx.@@.mc[mcnum]["kids"] = ltx.@@.mc[mcnum]["kids"] or { }
+ local kidtable = {kid=kid,page=page}
+ tableinsert(ltx.@@.mc[mcnum]["kids"], kidtable )
+end
+% \end{macrocode}
+% \end{macro}
+
+% \begin{macro}
+% {
+% ltx.@@.func.mc_num_of_kids
+% }
+% This function returns the number of kids a mc |mcnum| has. We need to account for
+% the case that a mc can have no kids.
+% \begin{macrocode}
+function ltx.@@.func.mc_num_of_kids (mcnum)
+ local num = 0
+ if ltx.@@.mc[mcnum] and ltx.@@.mc[mcnum]["kids"] then
+ num = #ltx.@@.mc[mcnum]["kids"]
+ end
+ ltx.@@.trace.log ("INFO MC-KID-NUMBERS: " .. mcnum .. "has " .. num .. "KIDS",4)
+ return num
+end
+% \end{macrocode}
+% \end{macro}
+% \subsection{Functions to insert the pdf literals}
+% \begin{macro}{@@_insert_emc_node}
+% This insert the emc node.
+% \begin{macrocode}
local function @@_insert_emc_node (head,current)
local emcnode = nodenew("whatsit","pdf_literal")
emcnode.data = "EMC"
@@ -295,8 +575,11 @@ local function @@_insert_emc_node (head,current)
head = node.insert_before(head,current,emcnode)
return head
end
-
-
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{@@_insert_bmc_node}
+% This inserts a simple bmc node
+% \begin{macrocode}
local function @@_insert_bmc_node (head,current,tag)
local bmcnode = nodenew("whatsit","pdf_literal")
bmcnode.data = "/"..tag.." BMC"
@@ -304,7 +587,12 @@ local function @@_insert_bmc_node (head,current,tag)
head = node.insert_before(head,current,bmcnode)
return head
end
-
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{@@_insert_bdc_node}
+% This inserts a bcd node with a fix dict.
+% TODO: check if this is still used, now that we create properties.
+% \begin{macrocode}
local function @@_insert_bdc_node (head,current,tag,dict)
local bdcnode = nodenew("whatsit","pdf_literal")
bdcnode.data = "/"..tag.."<<"..dict..">> BDC"
@@ -312,8 +600,28 @@ local function @@_insert_bdc_node (head,current,tag,dict)
head = node.insert_before(head,current,bdcnode)
return head
end
-
--- this is for debugging the space chars
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{@@_pdf_object_ref,ltx.@@.func.pdf_object_ref}
+% This allows to reference a pdf object reserved with the l3pdf command by name.
+% The return value is |n 0 R|, if the object doesn't exist, n is 0.
+% TODO: is uses internal l3pdf commands, this should be properly supported by l3pdf
+% \begin{macrocode}
+local function @@_pdf_object_ref (name)
+ local tokenname = 'c__pdf_backend_object_'..name..'_int'
+ local object = token.create(tokenname).index..' 0 R'
+ return object
+end
+ltx.@@.func.pdf_object_ref=@@_pdf_object_ref
+% \end{macrocode}
+% \end{macro}
+%
+% \section{Function for the real space chars}
+% \begin{macro}{@@_show_spacemark}
+% A debugging function, it is used to
+% inserts red color markers in the places where space chars can go, it can have
+% side effects so not always reliable, but ok.
+% \begin{macrocode}
local function @@_show_spacemark (head,current,color,height)
local markcolor = color or "1 0 0"
local markheight = height or 10
@@ -323,7 +631,24 @@ local function @@_show_spacemark (head,current,color,height)
head = node.insert_after(head,current,pdfstring)
return head
end
-
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{@@_fakespace,ltx.@@.func.fakespace}
+% This is used to define a lua version of |\pdffakespace|
+% \begin{macrocode}
+local function @@_fakespace()
+ tex.setattribute(iwspaceattributeid,1)
+ tex.setattribute(iwfontattributeid,font.current())
+end
+ltx.@@.func.fakespace = @@_fakespace
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{@@_mark_spaces}
+% a function to mark up places where real space chars should be inserted.
+% It only sets attributes, these are then be used in a later traversing
+% which inserts the actual spaces.
+% When space handling is activated this function is inserted in some callbacks.
+% \begin{macrocode}
--[[ a function to mark up places where real space chars should be inserted
it only sets an attribute.
--]]
@@ -353,13 +678,15 @@ local function @@_mark_spaces (head)
end
-- look also back
if glyph.prev and (glyph.prev.id == GLUE)
- and not inside_math and (glyph.prev.width >0) and not nodehasattribute(glyph.prev,iwspaceattributeid)
+ and not inside_math
+ and (glyph.prev.width >0)
+ and not nodehasattribute(glyph.prev,iwspaceattributeid)
then
nodesetattribute(glyph.prev,iwspaceattributeid,1)
nodesetattribute(glyph.prev,iwfontattributeid,glyph.font)
-- for debugging
- if ltx.__tag.trace.showspaces then
- __tag_show_spacemark (head,glyph)
+ if ltx.@@.trace.showspaces then
+ @@_show_spacemark (head,glyph)
end
end
elseif id == PENALTY then
@@ -381,7 +708,18 @@ local function @@_mark_spaces (head)
end
return head
end
-
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}
+% {
+% @@_activate_mark_space,
+% ltx.@@.func.markspaceon,
+% @@_activate_mark_space,
+% ltx.@@.func.markspaceoff
+% }
+% Theses functions add/remove the function which marks the spaces to the callbacks
+% |pre_linebreak_filter| and |hpack_filter|
+% \begin{macrocode}
local function @@_activate_mark_space ()
if not luatexbase.in_callback ("pre_linebreak_filter","markspaces") then
luatexbase.add_to_callback("pre_linebreak_filter",@@_mark_spaces,"markspaces")
@@ -397,23 +735,150 @@ local function @@_deactivate_mark_space ()
luatexbase.remove_from_callback("hpack_filter","markspaces")
end
end
---
-ltx.@@.func.markspaceoff=@@_deactivate_mark_space
+ltx.@@.func.markspaceoff=@@_deactivate_mark_space
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}
+% {
+% default_space_char,
+% default_fontid,
+% }
+% We need two local variable to setup a default space char.
+% \begin{macrocode}
local default_space_char = node.new(GLYPH)
local default_fontid = font.id("TU/lmr/m/n/10")
default_space_char.char = 32
default_space_char.font = default_fontid
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}
+% {
+% @@_space_chars_shipout,
+% ltx.@@.func.space_chars_shipout,
+% }
+% These is the main function to insert real space chars. It inserts a
+% glyph before every glue which has been marked previously. The attributes
+% are copied from the glue, so if the tagging is done later,
+% it will be tagged like it.
+% \begin{macrocode}
+local function @@_space_chars_shipout (box)
+ local head = box.head
+ if head then
+ for n in node.traverse(head) do
+ local spaceattr = nodegetattribute(n,iwspaceattributeid) or -1
+ if n.id == HLIST then -- enter the hlist
+ @@_space_chars_shipout (n)
+ elseif n.id == VLIST then -- enter the vlist
+ @@_space_chars_shipout (n)
+ elseif n.id == GLUE then
+ if ltx.@@.trace.showspaces and spaceattr==1 then
+ @@_show_spacemark (head,n,"0 1 0")
+ end
+ if spaceattr==1 then
+ local space
+ local space_char = node.copy(default_space_char)
+ local curfont = nodegetattribute(n,iwfontattributeid)
+ ltx.@@.trace.log ("INFO SPACE-FUNCTION-FONT: ".. tostring(curfont),3)
+ if curfont and luaotfload.aux.slot_of_name(curfont,"space") then
+ space_char.font=curfont
+ end
+ head, space = node.insert_before(head, n, space_char) --
+ n.width = n.width - space.width
+ space.attr = n.attr
+ end
+ end
+ end
+ end
+end
-local function @@_insert_space_char (head,n,fontid)
- if luaotfload.aux.slot_of_name(fontid,"space") then
- local space
- -- head, space = node.insert_before(head, n, ) -- Set the right font
- -- n.width = n.width - space.width
- -- space.attr = n.attr
- end
+function ltx.@@.func.space_chars_shipout (box)
+ @@_space_chars_shipout (box)
+end
+% \end{macrocode}
+% \end{macro}
+%
+% \section{Function for the tagging}
+% \begin{macro}
+% {
+% ltx.@@.func.mc_insert_kids
+% }
+% This is the main function to insert the
+% K entry into a StructElem object. It is used in tagpdf-mc-luacode module.
+% The |single| attribute allows to handle the case that a single
+% mc on the tex side can have more than one kid after the processing here,
+% and so we get the correct array/non array setup.
+% \begin{macrocode}
+function ltx.@@.func.mc_insert_kids (mcnum,single)
+ if ltx.@@.mc[mcnum] then
+ ltx.@@.trace.log("INFO TEX-MC-INSERT-KID-TEST: " .. mcnum,4)
+ if ltx.@@.mc[mcnum]["kids"] then
+ if #ltx.@@.mc[mcnum]["kids"] > 1 and single==1 then
+ tex.sprint("[")
+ end
+ for i,kidstable in ipairs( ltx.@@.mc[mcnum]["kids"] ) do
+ local kidnum = kidstable["kid"]
+ local kidpage = kidstable["page"]
+ local kidpageobjnum = pdfpageref(kidpage)
+ ltx.@@.trace.log("INFO TEX-MC-INSERT-KID: " .. mcnum ..
+ " insert KID " ..i..
+ " with num " .. kidnum ..
+ " on page " .. kidpage.."/"..kidpageobjnum,3)
+ tex.sprint(catlatex,"<</Type /MCR /Pg "..kidpageobjnum .. " 0 R /MCID "..kidnum.. ">> " )
+ end
+ if #ltx.@@.mc[mcnum]["kids"] > 1 and single==1 then
+ tex.sprint("]")
+ end
+ else
+ -- this is typically not a problem, e.g. empty hbox in footer/header can
+ -- trigger this warning.
+ ltx.@@.trace.log("WARN TEX-MC-INSERT-NO-KIDS: "..mcnum.." has no kids",2)
+ if single==1 then
+ tex.sprint("null")
+ end
+ end
+ else
+ ltx.@@.trace.log("WARN TEX-MC-INSERT-MISSING: "..mcnum.." doesn't exist",0)
+ end
+end
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{ltx.@@.func.store_struct_mcabs}
+% This function is used in the tagpdf-mc-luacode. It store the absolute count
+% of the mc into the current structure. This must be done ordered.
+% \begin{macrocode}
+function ltx.@@.func.store_struct_mcabs (structnum,mcnum)
+ ltx.@@.struct[structnum]=ltx.@@.struct[structnum] or { }
+ ltx.@@.struct[structnum]["mc"]=ltx.@@.struct[structnum]["mc"] or { }
+ -- a structure can contain more than on mc chunk, the content should be ordered
+ tableinsert(ltx.@@.struct[structnum]["mc"],mcnum)
+ ltx.@@.trace.log("INFO TEX-MC-INTO-STRUCT: "..
+ mcnum.." inserted in struct "..structnum,3)
+ -- but every mc can only be in one structure
+ ltx.@@.mc[mcnum]= ltx.@@.mc[mcnum] or { }
+ ltx.@@.mc[mcnum]["parent"] = structnum
end
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{ltx.@@.func.store_mc_in_page}
+% This is used in the traversing code and stores the relation between
+% abs count and page count.
+% \begin{macrocode}
+-- pay attention: lua counts arrays from 1, tex pages from one
+-- mcid and arrays in pdf count from 0.
+function ltx.@@.func.store_mc_in_page (mcnum,mcpagecnt,page)
+ ltx.@@.page[page] = ltx.@@.page[page] or {}
+ ltx.@@.page[page][mcpagecnt] = mcnum
+ ltx.@@.trace.log("INFO TAG-MC-INTO-PAGE: page " .. page ..
+ ": inserting MCID " .. mcpagecnt .. " => " .. mcnum,3)
+end
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{ltx.@@.func.mark_page_elements}
+% This is the main traversing function. See the lua comment for more details.
+% \begin{macrocode}
--[[
Now follows the core function
It wades through the shipout box and checks the attributes
@@ -433,22 +898,35 @@ end
function ltx.@@.func.mark_page_elements (box,mcpagecnt,mccntprev,mcopen,name,mctypeprev)
local name = name or ("SOMEBOX")
local mctypeprev = mctypeprev or -1
- local abspage = status.total_pages + 1 -- the real counter is increased inside the box so one off
- -- if the callback is not used.
- ltx.@@.trace.log ("PAGE " .. abspage,3)
- ltx.@@.trace.log ("FUNC ARGS: pagecnt".. mcpagecnt.." prev "..mccntprev .. " type prev "..mctypeprev,4)
- ltx.@@.trace.log ("TRAVERSING BOX ".. tostring(name).." TYPE ".. node.type(node.getid(box)),3)
+ local abspage = status.total_pages + 1 -- the real counter is increased
+ -- inside the box so one off
+ -- if the callback is not used. (???)
+ ltx.@@.trace.log ("INFO TAG-ABSPAGE: " .. abspage,3)
+ ltx.@@.trace.log ("INFO TAG-ARGS: pagecnt".. mcpagecnt..
+ " prev "..mccntprev ..
+ " type prev "..mctypeprev,4)
+ ltx.@@.trace.log ("INFO TAG-TRAVERSING-BOX: ".. tostring(name)..
+ " TYPE ".. node.type(node.getid(box)),3)
local head = box.head -- ShipoutBox is a vlist?
if head then
mccnthead, mctypehead,taghead = @@_get_mc_cnt_type_tag (head)
- ltx.@@.trace.log ("HEAD " .. node.type(node.getid(head)).. " MC"..tostring(mccnthead).." => TAG "..tostring(mctypehead).." => "..tostring(taghead),3)
+ ltx.@@.trace.log ("INFO TAG-HEAD: " ..
+ node.type(node.getid(head))..
+ " MC"..tostring(mccnthead)..
+ " => TAG " .. tostring(mctypehead)..
+ " => ".. tostring(taghead),3)
else
- ltx.@@.trace.log ("HEAD is ".. tostring(head),3)
+ ltx.@@.trace.log ("INFO TAG-NO-HEAD: head is "..
+ tostring(head),3)
end
for n in node.traverse(head) do
local mccnt, mctype, tag = @@_get_mc_cnt_type_tag (n)
local spaceattr = nodegetattribute(n,iwspaceattributeid) or -1
- ltx.@@.trace.log ("NODE ".. node.type(node.getid(n)).." MC"..tostring(mccnt).." => TAG "..tostring(mctype).." => " .. tostring(tag),3)
+ ltx.@@.trace.log ("INFO TAG-NODE: "..
+ node.type(node.getid(n))..
+ " MC".. tostring(mccnt)..
+ " => TAG ".. tostring(mctype)..
+ " => " .. tostring(tag),3)
if n.id == HLIST
then -- enter the hlist
mcopen,mcpagecnt,mccntprev,mctypeprev=
@@ -456,83 +934,81 @@ function ltx.@@.func.mark_page_elements (box,mcpagecnt,mccntprev,mcopen,name,mct
elseif n.id == VLIST then -- enter the vlist
mcopen,mcpagecnt,mccntprev,mctypeprev=
ltx.@@.func.mark_page_elements (n,mcpagecnt,mccntprev,mcopen,"INTERNAL VLIST",mctypeprev)
- elseif n.id == GLUE then -- at glue real space chars are inserted, for the rest it is ignored
- -- for debugging
- if ltx.@@.trace.showspaces and spaceattr==1 then
- @@_show_spacemark (head,n,"0 1 0")
- end
- if spaceattr==1 then
- local space
- local space_char = node.copy(default_space_char)
- local curfont = nodegetattribute(n,iwfontattributeid)
- ltx.@@.trace.log ("FONT ".. tostring(curfont),3)
- if curfont and luaotfload.aux.slot_of_name(curfont,"space") then
- space_char.font=curfont
- end
- head, space = node.insert_before(head, n, space_char) --
- n.width = n.width - space.width
- space.attr = n.attr
- end
+ elseif n.id == GLUE then -- at glue real space chars are inserted, but this has
+ -- been done if the previous shipout wandering, so here it is ignored
elseif n.id == LOCAL_PAR then -- local_par is ignored
elseif n.id == PENALTY then -- penalty is ignored
elseif n.id == KERN then -- kern is ignored
- ltx.@@.trace.log ("SUBTYPE KERN ".. n.subtype,3)
+ ltx.@@.trace.log ("INFO TAG-KERN-SUBTYPE: "..
+ node.type(node.getid(n)).." "..n.subtype,4)
else
-- math is currently only logged.
-- we could mark the whole as math
-- for inner processing the mlist_to_hlist callback is probably needed.
if n.id == MATH then
- ltx.@@.trace.log("NODE "..node.type(node.getid(n)).." "..@@_get_mathsubtype(n),3)
+ ltx.@@.trace.log("INFO TAG-MATH-SUBTYPE: "..
+ node.type(node.getid(n)).." "..@@_get_mathsubtype(n),4)
end
-- endmath
- ltx.@@.trace.log("CURRENT "..mccnt.." PREV "..mccntprev,3)
+ ltx.@@.trace.log("INFO TAG-MC-COMPARE: current "..
+ mccnt.." prev "..mccntprev,4)
if mccnt~=mccntprev then -- a new mc chunk
- ltx.@@.trace.log ("NODE ".. node.type(node.getid(n)).." MC"..tostring(mccnt).." <=> PREVIOUS "..tostring(mccntprev),3)
+ ltx.@@.trace.log ("INFO TAG-NEW-MC-NODE: "..
+ node.type(node.getid(n))..
+ " MC"..tostring(mccnt)..
+ " <=> PREVIOUS "..tostring(mccntprev),4)
if mcopen~=0 then -- there is a chunk open, close it (hope there is only one ...
box.list=@@_insert_emc_node (box.list,n)
mcopen = mcopen - 1
- ltx.@@.trace.log ("INSERT EMC " .. mcpagecnt .. " MCOPEN = " .. mcopen,2)
+ ltx.@@.trace.log ("INFO TAG-INSERT-EMC: " ..
+ mcpagecnt .. " MCOPEN = " .. mcopen,3)
if mcopen ~=0 then
- ltx.@@.trace.log ("!WARNING! open mc" .. " MCOPEN = " .. mcopen,1)
+ ltx.@@.trace.log ("WARN TAG-OPEN-MC: " .. mcopen,1)
end
end
if ltx.@@.mc[mccnt] then
if ltx.@@.mc[mccnt]["artifact"] then
- ltx.@@.trace.log("THIS IS AN ARTIFACT of type "..tostring(ltx.@@.mc[mccnt]["artifact"]),3)
+ ltx.@@.trace.log("INFO TAG-INSERT-ARTIFACT: "..
+ tostring(ltx.@@.mc[mccnt]["artifact"]),3)
if ltx.@@.mc[mccnt]["artifact"] == "" then
box.list = @@_insert_bmc_node (box.list,n,"Artifact")
else
box.list = @@_insert_bdc_node (box.list,n,"Artifact", "/Type /"..ltx.@@.mc[mccnt]["artifact"])
end
else
- ltx.@@.trace.log("THIS IS A TAG "..tostring(tag),3)
+ ltx.@@.trace.log("INFO TAG-INSERT-TAG: "..
+ tostring(tag),3)
mcpagecnt = mcpagecnt +1
- ltx.@@.trace.log ("INSERT BDC "..mcpagecnt,2)
+ ltx.@@.trace.log ("INFO TAG-INSERT-BDC: "..mcpagecnt,3)
local dict= "/MCID "..mcpagecnt
if ltx.@@.mc[mccnt]["raw"] then
- ltx.@@.trace.log("RAW CONTENT"..tostring(ltx.@@.mc[mccnt]["raw"]),3)
+ ltx.@@.trace.log("INFO TAG-USE-RAW: "..
+ tostring(ltx.@@.mc[mccnt]["raw"]),3)
dict= dict .. " " .. ltx.@@.mc[mccnt]["raw"]
end
if ltx.@@.mc[mccnt]["alt"] then
- ltx.@@.trace.log("RAW CONTENT"..tostring(ltx.@@.mc[mccnt]["alt"]),3)
+ ltx.@@.trace.log("INFO TAG-USE-ALT: "..
+ tostring(ltx.@@.mc[mccnt]["alt"]),3)
dict= dict .. " " .. ltx.@@.mc[mccnt]["alt"]
end
if ltx.@@.mc[mccnt]["actualtext"] then
- ltx.@@.trace.log("RAW CONTENT"..tostring(ltx.@@.mc[mccnt]["actualtext"]),3)
+ ltx.@@.trace.log("INFO TAG-USE-ACTUALTEXT: "..
+ tostring(ltx.@@.mc[mccnt]["actualtext"]),3)
dict= dict .. " " .. ltx.@@.mc[mccnt]["actualtext"]
end
box.list = @@_insert_bdc_node (box.list,n,tag, dict)
ltx.@@.func.store_mc_kid (mccnt,mcpagecnt,abspage)
ltx.@@.func.store_mc_in_page(mccnt,mcpagecnt,abspage)
- ltx.@@.trace.show_mc_data (mccnt)
+ ltx.@@.trace.show_mc_data (mccnt,3)
end
mcopen = mcopen + 1
else
- ltx.@@.trace.log("THIS HAS NOT BEEN TAGGED",1)
- -- perhaps code that tag a artifact can be added ...
if tagunmarkedbool.mode == truebool.mode then
+ ltx.@@.trace.log("INFO TAG-NOT-TAGGED: this has not been tagged, using artifact",2)
box.list = @@_insert_bmc_node (box.list,n,"Artifact")
mcopen = mcopen + 1
+ else
+ ltx.@@.trace.log("WARN TAG-NOT-TAGGED: this has not been tagged",1)
end
end
mccntprev = mccnt
@@ -541,18 +1017,29 @@ function ltx.@@.func.mark_page_elements (box,mcpagecnt,mccntprev,mcopen,name,mct
end -- end for
if head then
mccnthead, mctypehead,taghead = @@_get_mc_cnt_type_tag (head)
- ltx.@@.trace.log ("ENDHEAD " .. node.type(node.getid(head)).. " MC"..tostring(mccnthead).." => TAG "..tostring(mctypehead).." => "..tostring(taghead),3)
+ ltx.@@.trace.log ("INFO TAG-ENDHEAD: " ..
+ node.type(node.getid(head))..
+ " MC"..tostring(mccnthead)..
+ " => TAG "..tostring(mctypehead)..
+ " => "..tostring(taghead),4)
else
- ltx.@@.trace.log ("ENDHEAD is ".. tostring(head),3)
+ ltx.@@.trace.log ("INFO TAG-ENDHEAD: ".. tostring(head),4)
end
- ltx.@@.trace.log ("QUITTING TRAVERSING BOX ".. tostring(name).." TYPE ".. node.type(node.getid(box)),3)
+ ltx.@@.trace.log ("INFO TAG-QUITTING-BOX "..
+ tostring(name)..
+ " TYPE ".. node.type(node.getid(box)),4)
return mcopen,mcpagecnt,mccntprev,mctypeprev
end
-
-
-function ltx.__tag.func.mark_shipout (box)
- mcopen = ltx.__tag.func.mark_page_elements (box,-1,-100,0,"Shipout",-1)
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{ltx.@@.func.mark_shipout}
+% This is the function used in the callback. Beside calling the traversing
+% function it also checks if there is an open MC-chunk from a page
+% break and insert the needed EMC literal.
+% \begin{macrocode}
+function ltx.@@.func.mark_shipout (box)
+ mcopen = ltx.@@.func.mark_page_elements (box,-1,-100,0,"Shipout",-1)
if mcopen~=0 then -- there is a chunk open, close it (hope there is only one ...
local emcnode = nodenew("whatsit","pdf_literal")
local list = box.list
@@ -561,199 +1048,28 @@ function ltx.__tag.func.mark_shipout (box)
if list then
list = node.insert_after (list,node.tail(list),emcnode)
mcopen = mcopen - 1
- ltx.__tag.trace.log ("INSERT LAST EMC, MCOPEN = " .. mcopen,2)
+ ltx.@@.trace.log ("INFO SHIPOUT-INSERT-LAST-EMC: MCOPEN " .. mcopen,3)
else
- ltx.__tag.trace.log ("UPS ",1)
+ ltx.@@.trace.log ("WARN SHIPOUT-UPS: this shouldn't happen",0)
end
if mcopen ~=0 then
- ltx.__tag.trace.log ("!WARNING! open mc" .. " MCOPEN = " .. mcopen,1)
+ ltx.@@.trace.log ("WARN SHIPOUT-MC-OPEN: " .. mcopen,1)
end
end
end
-
-
-function ltx.@@.trace.show_seq (seq)
- if (type(seq) == "table") then
- for i,v in ipairs(seq) do
- @@_log ("[" .. i .. "] => " .. tostring(v),1)
- end
- else
- @@_log ("sequence " .. tostring(seq) .. " not found",1)
- end
-end
-
-local @@_pairs_prop =
- function (prop)
- local a = {}
- for n in pairs(prop) do tableinsert(a, n) end
- table.sort(a)
- local i = 0 -- iterator variable
- local iter = function () -- iterator function
- i = i + 1
- if a[i] == nil then return nil
- else return a[i], prop[a[i]]
- end
- end
- return iter
- end
-
-
-function ltx.@@.trace.show_prop (prop)
- if (type(prop) == "table") then
- for i,v in @@_pairs_prop (prop) do
- @@_log ("[" .. i .. "] => " .. tostring(v),1)
- end
- else
- @@_log ("prop " .. tostring(prop) .. " not found or not a table",1)
- end
- end
-
-
-local @@_get_num_from =
- function (tag)
- if ltx.@@.tables["g_@@_role_tags_prop"][tag] then
- a= ltx.@@.tables["g_@@_role_tags_prop"][tag]
- else
- a= -1
- end
- return a
- end
-
-ltx.@@.func.get_num_from = @@_get_num_from
-
-function ltx.@@.func.output_num_from (tag)
- local num = @@_get_num_from (tag)
- tex.sprint(catlatex,num)
- if num == -1 then
- @@_log ("Unknown tag "..tag.." used")
- end
-end
-
-local @@_get_tag_from =
- function (num)
- if ltx.@@.tables["g_@@_role_tags_seq"][num] then
- a = ltx.@@.tables["g_@@_role_tags_seq"][num]
- else
- a= "UNKNOWN"
- end
- return a
-end
-
-ltx.@@.func.get_tag_from = @@_get_tag_from
-
-function ltx.@@.func.output_tag_from (num)
- tex.sprint(catlatex,@@_get_tag_from (num))
-end
-
-function ltx.@@.func.store_mc_data (num,key,data)
- ltx.@@.mc[num] = ltx.@@.mc[num] or { }
- ltx.@@.mc[num][key] = data
- @@_log ("storing mc"..num..": "..tostring(key).."=>"..tostring(data))
-end
-
-function ltx.@@.trace.show_mc_data (num)
- if ltx.@@ and ltx.@@.mc and ltx.@@.mc[num] then
- for k,v in pairs(ltx.@@.mc[num]) do
- @@_log ("mc"..num..": "..tostring(k).."=>"..tostring(v),3)
- end
- if ltx.@@.mc[num]["kids"] then
- @@_log ("mc" .. num .. " has " .. #ltx.@@.mc[num]["kids"] .. " kids",3)
- for k,v in ipairs(ltx.@@.mc[num]["kids"]) do
- @@_log ("mc ".. num .. " kid "..k.." =>" .. v.kid.." on page " ..v.page,3)
- end
- end
- else
- @@_log ("mc"..num.." not found",3)
- end
-end
-
-function ltx.@@.trace.show_all_mc_data (max)
- for i = 1, max do
- ltx.@@.trace.show_mc_data (i)
- end
-end
-
-
-function ltx.@@.func.store_mc_label (label,num)
- ltx.@@.mc["labels"] = ltx.@@.mc["labels"] or { }
- ltx.@@.mc.labels[label] = num
-end
-
-function ltx.@@.func.store_mc_kid (mcnum,kid,page)
- ltx.@@.trace.log("MC"..mcnum.." STORING KID" .. kid.." on page " .. page,3)
- ltx.@@.mc[mcnum]["kids"] = ltx.@@.mc[mcnum]["kids"] or { }
- local kidtable = {kid=kid,page=page}
- tableinsert(ltx.@@.mc[mcnum]["kids"], kidtable )
-end
-
-
-function ltx.@@.func.mc_num_of_kids (mcnum)
- local num = 0
- if ltx.@@.mc[mcnum] and ltx.@@.mc[mcnum]["kids"] then
- num = #ltx.@@.mc[mcnum]["kids"]
- end
- ltx.@@.trace.log ("MC" .. mcnum .. "has " .. num .. "KIDS",4)
- return num
-end
-
-function ltx.@@.func.mc_insert_kids (mcnum,single)
- if ltx.@@.mc[mcnum] then
- ltx.@@.trace.log("MC-KIDS test " .. mcnum,4)
- if ltx.@@.mc[mcnum]["kids"] then
- if #ltx.@@.mc[mcnum]["kids"] > 1 and single==1 then
- tex.sprint("[")
- end
- for i,kidstable in ipairs( ltx.@@.mc[mcnum]["kids"] ) do
- local kidnum = kidstable["kid"]
- local kidpage = kidstable["page"]
- local kidpageobjnum = pdfpageref(kidpage)
- ltx.@@.trace.log("MC" .. mcnum .. " insert KID " ..i.. " with num " .. kidnum .. " on page " .. kidpage.."/"..kidpageobjnum,3)
- tex.sprint(catlatex,"<</Type /MCR /Pg "..kidpageobjnum .. " 0 R /MCID "..kidnum.. ">> " )
- end
- if #ltx.@@.mc[mcnum]["kids"] > 1 and single==1 then
- tex.sprint("]")
- end
- else
- ltx.@@.trace.log("WARN! MC"..mcnum.." has no kids",0)
- if single==1 then
- tex.sprint("null")
- end
- end
- else
- ltx.@@.trace.log("WARN! MC"..mcnum.." doesn't exist",0)
- end
-end
-
-
-function ltx.@@.func.store_struct_mcabs (structnum,mcnum)
- ltx.@@.struct[structnum]=ltx.@@.struct[structnum] or { }
- ltx.@@.struct[structnum]["mc"]=ltx.@@.struct[structnum]["mc"] or { }
- -- a structure can contain more than on mc chunk, the content should be ordered
- tableinsert(ltx.@@.struct[structnum]["mc"],mcnum)
- ltx.@@.trace.log("MCNUM "..mcnum.." insert in struct "..structnum,3)
- -- but every mc can only be in one structure
- ltx.@@.mc[mcnum]= ltx.@@.mc[mcnum] or { }
- ltx.@@.mc[mcnum]["parent"] = structnum
-end
-
-function ltx.@@.trace.show_struct_data (num)
- if ltx.@@ and ltx.@@.struct and ltx.@@.struct[num] then
- for k,v in ipairs(ltx.@@.struct[num]) do
- @@_log ("struct "..num..": "..tostring(k).."=>"..tostring(v))
- end
- else
- @@_log ("struct "..num.." not found ")
- end
-end
-
--- pay attention: lua counts arrays from 1, tex pages from one
--- mcid and arrays in pdf count from 0.
-function ltx.@@.func.store_mc_in_page (mcnum,mcpagecnt,page)
- ltx.@@.page[page] = ltx.@@.page[page] or {}
- ltx.@@.page[page][mcpagecnt] = mcnum
- ltx.@@.trace.log("PAGE " .. page .. ": inserting MCID " .. mcpagecnt .. " => " .. mcnum,3)
-end
-
+% \end{macrocode}
+% \end{macro}
+
+% \section{Parenttree}
+% \begin{macro}
+% {
+% ltx.@@.func.fill_parent_tree_line,
+% ltx.@@.func.output_parenttree
+% }
+% These functions create the parent tree. The second, main function
+% is used in the tagpdf-tree code.
+% TODO check if the tree code can move into the backend code.
+% \begin{macrocode}
function ltx.@@.func.fill_parent_tree_line (page)
-- we need to get page-> i=kid -> mcnum -> structnum
-- pay attention: the kid numbers and the page number in the parent tree start with 0!
@@ -761,33 +1077,41 @@ function ltx.@@.func.fill_parent_tree_line (page)
local pdfpage = page-1
if ltx.@@.page[page] and ltx.@@.page[page][0] then
mcchunks=#ltx.@@.page[page]
- ltx.@@.trace.log("PAGETREE PAGE "..page.." has "..mcchunks.."+1 Elements ",3)
+ ltx.@@.trace.log("INFO PARENTTREE-NUM: page "..
+ page.." has "..mcchunks.."+1 Elements ",4)
for i=0,mcchunks do
- ltx.@@.trace.log("PAGETREE CHUNKS "..ltx.@@.page[page][i],3)
+ -- what does this log??
+ ltx.@@.trace.log("INFO PARENTTREE-CHUNKS: "..
+ ltx.@@.page[page][i],4)
end
if mcchunks == 0 then
-- only one chunk so no need for an array
local mcnum = ltx.@@.page[page][0]
local structnum = ltx.@@.mc[mcnum]["parent"]
local propname = "g_@@_struct_"..structnum.."_prop"
- local objref = ltx.@@.tables[propname]["objref"] or "XXXX"
- ltx.@@.trace.log("=====>"..tostring(objref),5)
+ --local objref = ltx.@@.tables[propname]["objref"] or "XXXX"
+ local objref = @@_pdf_object_ref('@@/struct/'..structnum)
+ ltx.@@.trace.log("INFO PARENTTREE-STRUCT-OBJREF: =====>"..
+ tostring(objref),5)
numsentry = pdfpage .. " [".. objref .. "]"
- ltx.@@.trace.log("PAGETREE PAGE" .. page.. " NUM ENTRY = ".. numsentry,3)
+ ltx.@@.trace.log("INFO PARENTTREE-NUMENTRY: page " ..
+ page.. " num entry = ".. numsentry,3)
else
numsentry = pdfpage .. " ["
for i=0,mcchunks do
local mcnum = ltx.@@.page[page][i]
local structnum = ltx.@@.mc[mcnum]["parent"] or 0
local propname = "g_@@_struct_"..structnum.."_prop"
- local objref = ltx.@@.tables[propname]["objref"] or "XXXX"
+ --local objref = ltx.@@.tables[propname]["objref"] or "XXXX"
+ local objref = @@_pdf_object_ref('@@/struct/'..structnum)
numsentry = numsentry .. " ".. objref
end
numsentry = numsentry .. "] "
- ltx.@@.trace.log("PAGETREE PAGE" .. page.. " NUM ENTRY = ".. numsentry,3)
+ ltx.@@.trace.log("INFO PARENTTREE-NUMENTRY: page " ..
+ page.. " num entry = ".. numsentry,3)
end
else
- ltx.@@.trace.log ("PAGETREE: NO DATA FOR PAGE "..page,3)
+ ltx.@@.trace.log ("INFO PARENTTREE-NO-DATA: page "..page,3)
end
return numsentry
end
@@ -798,7 +1122,10 @@ function ltx.@@.func.output_parenttree (abspage)
tex.sprint(catlatex,line)
end
end
-
-
+% \end{macrocode}
+% \end{macro}
+% \begin{macrocode}
%</lua>
% \end{macrocode}
+% \end{implementation}
+% \PrintIndex