summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/tagpdf/tagpdf-struct-code.sty
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2018-07-05 21:45:46 +0000
committerKarl Berry <karl@freefriends.org>2018-07-05 21:45:46 +0000
commiteef245751e7d3cec3ce8db3dda9f93818e1a7118 (patch)
tree995036273168036838cec88e6ff67d05b7942319 /Master/texmf-dist/tex/latex/tagpdf/tagpdf-struct-code.sty
parentf8fda7824b2b8cdebc2f57a8dc1aefdec29b14e9 (diff)
tagpdf (5jul18)
git-svn-id: svn://tug.org/texlive/trunk@48146 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/tagpdf/tagpdf-struct-code.sty')
-rw-r--r--Master/texmf-dist/tex/latex/tagpdf/tagpdf-struct-code.sty398
1 files changed, 398 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/tagpdf/tagpdf-struct-code.sty b/Master/texmf-dist/tex/latex/tagpdf/tagpdf-struct-code.sty
new file mode 100644
index 00000000000..24345dfd196
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/tagpdf/tagpdf-struct-code.sty
@@ -0,0 +1,398 @@
+\ProvidesExplPackage {tagpdf-struct-code} {2018/07/04} {0.1}
+ {part of tagpdf - code related to storing structure}
+
+% I will use a latex counter for the structure count
+% to have a chance to avoid double structures in align etc
+
+\newcounter { g__uftag_struct_abs_int }
+\int_gzero:N \c@g__uftag_struct_abs_int
+
+
+\zref@newprop {tagstruct} [0] { \int_use:N \c@g__uftag_struct_abs_int }
+\zref@newlist {tagpdfstruct}
+\zref@addprop {tagpdfstruct}{tagstruct}
+
+% a sequence stores structnum -> the obj numbers
+% to allow easy mapping over the structures
+
+\__uftag_seq_new:N \g__uftag_struct_objR_seq
+
+% a sequence for the structure stack. When a sequence is opened it's number is put on the stack.
+\seq_new:N \g__uftag_struct_stack_seq
+\seq_gpush:Nn \g__uftag_struct_stack_seq {0}
+
+%this variables will hold the top entry and the parent on the stack
+\tl_new:N \l__uftag_struct_stack_parent_tmp_tl
+\tl_new:N \g__uftag_struct_stack_current_tl
+
+% I need at least one structure: the StructTreeRoot
+% normally it should have only one kid, e.g. the document element.
+
+% The data of the StructTreeRoot and the StructElem are in properties:
+% \g__uftag_struct_0_prop for the root
+% \g__uftag_struct_N_prop, N >=1
+% they have all the keys
+% objnum - number,
+% Type - StructTreeRoot or StructElem
+% num - number (identical to the num in the name, or 0 for the root)
+% and the keys from the two following lists
+% (the root has a special set of properties).
+% the values of the prop should be already escaped properly
+% when the entries are created (title,lange,alt,E,actualtext)
+
+
+\seq_new:N \c__uftag_struct_StructTreeRoot_entries_seq
+\seq_set_from_clist:Nn \c__uftag_struct_StructTreeRoot_entries_seq
+ {%p. 857/858
+ Type, % always /StructTreeRoot
+ K, % kid, dictionary or array of dictionaries
+ IDTree, % currently unused
+ ParentTree, % required,obj ref to the parent tree
+ ParentTreeNextKey, %optional
+ RoleMap,
+ ClassMap
+ }
+
+\seq_new:N \c__uftag_struct_StructElem_entries_seq
+\seq_set_from_clist:Nn \c__uftag_struct_StructElem_entries_seq
+ {%p 858 f
+ Type, %always /StructElem
+ S, %tag/type
+ P, %parent
+ ID, %optional
+ Pg, %obj num of starting page, optional
+ K, %kids
+ A, %attributes, probably unused
+ C, %class ""
+ %R,
+ T, %title, value in () or <>
+ Lang, %language
+ Alt, % value in () or <>
+ E, %abreviation
+ ActualText
+ }
+
+% I need an output handler for each prop, to get expandable output
+% see https://tex.stackexchange.com/questions/424208/expandable-version-of-a-expl3-command/424213#424213
+
+\cs_new:Nn \__uftag_struct_output_prop_aux:nn %#1 num, #2 key
+ {
+ \prop_if_in:cnT
+ { g__uftag_struct_#1_prop }
+ { #2 }
+ {
+ \c_space_tl/#2~ \prop_item:cn{ g__uftag_struct_#1_prop } { #2 }
+ }
+ }
+
+\cs_new:Nn \__uftag_new_output_prop_handler:n
+ {
+ \cs_new:cn { __uftag_struct_output_prop_#1:n }
+ {
+ \__uftag_struct_output_prop_aux:nn {#1}{##1}
+ }
+ }
+
+
+% the first one, the StructTreeRoot is special, so
+% created manually:
+\__uftag_prop_new:c { g__uftag_struct_0_prop }
+\__uftag_new_output_prop_handler:n {0}
+\tl_gset:Nn \g__uftag_struct_stack_current_tl {0}
+
+\__uftag_seq_new:c { g__uftag_struct_kids_0_seq}
+
+\__uftag_prop_gput:cno
+ { g__uftag_struct_0_prop }
+ { objnum}
+ { \c_uftag_tree_obj_structtreeroot_tl }
+
+\__uftag_prop_gput:cno
+ { g__uftag_struct_0_prop }
+ { Type }
+ { /StructTreeRoot }
+
+% the constants are defined in the tree code.
+\__uftag_prop_gput:cnx
+ { g__uftag_struct_0_prop }
+ { ParentTree }
+ { \c__uftag_tree_obj_parenttree_tl\c_space_tl 0\c_space_tl R }
+
+\__uftag_prop_gput:cnx
+ { g__uftag_struct_0_prop }
+ { RoleMap }
+ { \c__uftag_tree_obj_rolemap_tl\c_space_tl 0\c_space_tl R }
+
+\__uftag_prop_gput:cno
+ { g__uftag_struct_0_prop }
+ { entries }
+ { StructTreeRoot }
+
+\__uftag_prop_gput:cno
+ { g__uftag_struct_0_prop }
+ { num }
+ { 0 }
+
+% commands to store the kids
+% I don't compare the page objects number yet, but always add the /Pg key, perhaps later
+
+\cs_new:Nn \__uftag_struct_kid_mc_gput_right:nn %#1 structure num, #2 MCID absnum%
+ {
+ \__uftag_store_pdfpageref:Nn \l_tmpa_tl { \zref@extractdefault{mcid-#2}{tagabspage}{1} }
+ \__uftag_seq_gput_right:cx
+ { g__uftag_struct_kids_#1_seq }
+ { <<
+ /Type\c_space_tl/MCR\c_space_tl
+ /Pg\c_space_tl\l_tmpa_tl\c_space_tl0\c_space_tl R\c_space_tl
+ /MCID\c_space_tl\zref@extractdefault{mcid-#2}{tagmcid}{1}
+ >>
+ }
+ }
+
+\cs_new:Nn\__uftag_struct_kid_struct_gput_right:nn %#1 num of parent struct, #2 kid struct
+ {
+ \__uftag_seq_gput_right:cx
+ { g__uftag_struct_kids_#1_seq }
+ {
+ \prop_item:cn
+ { g__uftag_struct_#2_prop }
+ { objnum }
+ \c_space_tl 0 \c_space_tl R
+ }
+ }
+
+\cs_new:Nn \__uftag_struct_fill_kid_key:n %#1 is the struct num
+ {
+ \int_case:nnF
+ {
+ \seq_count:c
+ {
+ g__uftag_struct_kids_\prop_item:cn{ g__uftag_struct_#1_prop }{num}_seq
+ }
+ }
+ {
+ { 0 }
+ { } %no kids, do nothing
+ { 1 } % 1 kid, insert
+ {
+ \__uftag_prop_gput:cnx { g__uftag_struct_#1_prop } {K}
+ {
+ \seq_item:cn
+ {
+ g__uftag_struct_kids_\prop_item:cn{ g__uftag_struct_#1_prop }{num}_seq
+ }{1}
+ }
+ } %
+ }
+ { %many kids, use an array
+ \__uftag_prop_gput:cnx { g__uftag_struct_#1_prop } {K}
+ {
+ [
+ \seq_use:cn
+ {
+ g__uftag_struct_kids_\prop_item:cn{ g__uftag_struct_#1_prop }{num}_seq
+ }
+ {\c_space_tl}
+ ]
+ }
+ }
+ }
+
+% this command can be used for roots and structure elements
+% #1 is a num
+
+\tl_new:N \l_uftag_struct_dict_content_tl
+
+\cs_new:Nn \__uftag_struct_get_dict_content:n
+ {
+ \tl_set:Nn \l_uftag_struct_dict_content_tl {<<}
+ \seq_map_inline:cn
+ {
+ c__uftag_struct_\prop_item:cn{ g__uftag_struct_#1_prop }{entries}_entries_seq
+ }
+ {
+ \tl_put_right:Nx
+ \l_uftag_struct_dict_content_tl
+ {
+ \prop_if_in:cnT
+ { g__uftag_struct_#1_prop }
+ { ##1 }
+ {
+ \c_space_tl/##1~\prop_item:cn{ g__uftag_struct_#1_prop } { ##1 }
+ }
+ }
+ }
+ \tl_put_right:Nn \l_uftag_struct_dict_content_tl { >> }
+ }
+
+
+% #1 is the struct num
+\cs_new:Nn \__uftag_struct_write_obj:n
+ {
+ \prop_if_in:cnTF
+ { g__uftag_struct_#1_prop }
+ { objnum }
+ {
+ \__uftag_struct_fill_kid_key:n { #1 }
+ %\prop_show:c { g__uftag_struct_#1_prop }
+ \__uftag_struct_get_dict_content:n { #1 }
+ \__uftag_pdfuseobjnum:xx
+ { \prop_item:cn { g__uftag_struct_#1_prop } {objnum} }
+ {
+ \l_uftag_struct_dict_content_tl
+ }
+ }
+ {
+ \msg_error:nnn { tagpdf } { struct-no-objnum } { #1}
+ }
+ }
+
+% keys for the user commands
+% why did I call the submodule elem instead of struct?
+\keys_define:nn { tagpdf / elem }
+ {
+ label .tl_set:N = \l__uftag_struct_key_label_tl,
+ stash .bool_set:N = \l__uftag_struct_elem_stash_bool,
+ tag .code:n = % S property
+ {
+ \__uftag_pdf_escape_name:Nn \l__uftag_tmpa_tl { #1 }
+ \__uftag_prop_gput:cnx
+ { g__uftag_struct_\int_eval:n {\c@g__uftag_struct_abs_int}_prop }
+ { S }
+ { /\exp_not:V\l__uftag_tmpa_tl }
+ },
+ title .code:n = % T property
+ {
+ \__uftag_pdf_escape_string:Nn \l__uftag_tmpa_tl { #1 }
+ \tl_put_left:Nn \l__uftag_tmpa_tl {(^^fe^^ff}
+ \__uftag_prop_gput:cno
+ { g__uftag_struct_\int_eval:n {\c@g__uftag_struct_abs_int}_prop }
+ { T }
+ { \l__uftag_tmpa_tl) }
+ },
+ alttext .code:n = % Alt property
+ {
+ \__uftag_pdf_escape_string:Nn \l__uftag_tmpa_tl { #1 }
+ \tl_put_left:Nn \l__uftag_tmpa_tl {(^^fe^^ff}
+ \__uftag_prop_gput:cno
+ { g__uftag_struct_\int_eval:n {\c@g__uftag_struct_abs_int}_prop }
+ { Alt }
+ { \l__uftag_tmpa_tl) }
+ },
+ actualtext .code:n = % ActualText property
+ {
+ \__uftag_pdf_escape_hex:Nn \l__uftag_tmpa_tl {#1 }
+ \tl_put_left:Nn \l__uftag_tmpa_tl {<FEFF }
+ \__uftag_prop_gput:cno
+ { g__uftag_struct_\int_eval:n {\c@g__uftag_struct_abs_int}_prop }
+ { ActualText }
+ { \l__uftag_tmpa_tl>}
+ },
+}
+
+
+\cs_new:Nn \uftag_struct_begin:n
+ {
+ \group_begin:
+ \int_gincr:N \c@g__uftag_struct_abs_int
+ \__uftag_prop_new:c { g__uftag_struct_\int_eval:n { \c@g__uftag_struct_abs_int }_prop }
+ \__uftag_new_output_prop_handler:n {\int_eval:n { \c@g__uftag_struct_abs_int }}
+ \__uftag_seq_new:c { g__uftag_struct_kids_\int_eval:n { \c@g__uftag_struct_abs_int }_seq}
+ \__uftag_pdfreserveobjnum:N \l_tmpa_tl
+ \__uftag_prop_gput:cno
+ { g__uftag_struct_\int_eval:n { \c@g__uftag_struct_abs_int }_prop }
+ { objnum}
+ { \l_tmpa_tl }
+ \__uftag_prop_gput:cnx
+ { g__uftag_struct_\int_eval:n { \c@g__uftag_struct_abs_int }_prop }
+ { num}
+ { \int_eval:n { \c@g__uftag_struct_abs_int } }
+ \__uftag_prop_gput:cno
+ { g__uftag_struct_\int_eval:n { \c@g__uftag_struct_abs_int }_prop }
+ { Type }
+ { /StructElem }
+ \__uftag_prop_gput:cno
+ { g__uftag_struct_\int_eval:n { \c@g__uftag_struct_abs_int }_prop }
+ { entries }
+ { StructElem }
+ \keys_set:nn {tagpdf / elem} { #1 }
+ \__uftag_check_structure_has_tag:n { \int_eval:n {\c@g__uftag_struct_abs_int} }
+ \tl_if_empty:NF
+ {\l__uftag_struct_key_label_tl}
+ {
+ \zref@labelbylist{tagpdfstruct-\l__uftag_struct_key_label_tl}{tagpdfstruct}
+ }
+ %get the potential parent from the stack:
+ \seq_get:NNF
+ \g__uftag_struct_stack_seq
+ \l__uftag_struct_stack_parent_tmp_tl
+ {
+ \msg_error:nn { tagpdf } { struct-faulty-nesting }
+ }
+ \seq_gpush:NV \g__uftag_struct_stack_seq \c@g__uftag_struct_abs_int
+ \tl_gset:NV \g__uftag_struct_stack_current_tl \c@g__uftag_struct_abs_int
+ %\seq_show:N \g__uftag_struct_stack_seq
+ \bool_if:NF
+ \l__uftag_struct_elem_stash_bool
+ {%set the parent
+ \__uftag_prop_gput:cnx
+ { g__uftag_struct_\int_eval:n {\c@g__uftag_struct_abs_int}_prop }
+ { P }
+ {
+ \prop_item:cn { g__uftag_struct_\l__uftag_struct_stack_parent_tmp_tl _prop} { objnum }~0~R
+ }
+ %record this structure as kid:
+ %\tl_show:N \g__uftag_struct_stack_current_tl
+ %\tl_show:N \l__uftag_struct_stack_parent_tmp_tl
+ \__uftag_struct_kid_struct_gput_right:nn
+ { \l__uftag_struct_stack_parent_tmp_tl }
+ { \g__uftag_struct_stack_current_tl }
+ %\prop_show:c { g__uftag_struct_\g__uftag_struct_stack_current_tl _prop }
+ %\seq_show:c {g__uftag_struct_kids_\l__uftag_struct_stack_parent_tmp_tl _seq}
+ }
+ %\prop_show:c { g__uftag_struct_\g__uftag_struct_stack_current_tl _prop }
+ %\seq_show:c {g__uftag_struct_kids_\l__uftag_struct_stack_parent_tmp_tl _seq}
+ \group_end:
+ }
+
+\cs_new:Nn \uftag_struct_end:
+ {%take the current structure num from the stack:
+ %the objects are written later, lua mode hasn't all needed info yet
+ %\seq_show:N \g__uftag_struct_stack_seq
+ \seq_gpop:NNTF \g__uftag_struct_stack_seq \l_tmpa_tl
+ {
+ \__uftag_check_info_closing_struct:o { \g__uftag_struct_stack_current_tl }
+ }
+ { \__uftag_check_no_open_struck: }
+ % get the previous one, shouldn't be empty as the root should be there
+ \seq_get:NNTF \g__uftag_struct_stack_seq \l_tmpa_tl
+ {
+ \tl_gset:NV \g__uftag_struct_stack_current_tl \l_tmpa_tl
+ }
+ {
+ \__uftag_check_no_open_struck:
+ }
+ }
+
+\cs_new:Nn \uftag_struct_use:n %#1 is the label
+ {
+ \prop_if_exist:cTF
+ { g__uftag_struct_\zref@extractdefault{tagpdfstruct-#1}{tagstruct}{unknown}_prop }
+ {
+ \__uftag_check_struct_used:n {#1}
+ %add the label structure as kid to the current structure (can be the root)
+ \__uftag_struct_kid_struct_gput_right:nn
+ { \g__uftag_struct_stack_current_tl }
+ { \zref@extractdefault{tagpdfstruct-#1}{tagstruct}{0} }
+ %add the current structure to the labeled one as parents
+ \__uftag_prop_gput:cnx
+ { g__uftag_struct_\zref@extractdefault{tagpdfstruct-#1}{tagstruct}{0}_prop }
+ { P }
+ {
+ \prop_item:cn { g__uftag_struct_\g__uftag_struct_stack_current_tl _prop} { objnum }~0~R
+ }
+ }
+ {\msg_warning:nnn{tagpdf}{struct-label-unknown}{#1}}
+ }
+
+\endinput