[latex3-commits] [latex3/latex3] object-tracking: Use Lua-based tracking for indexed PDF objects (04569a959)

github at latex-project.org github at latex-project.org
Fri Apr 5 17:24:26 CEST 2024


Repository : https://github.com/latex3/latex3
On branch  : object-tracking
Link       : https://github.com/latex3/latex3/commit/04569a95996bfb33091c39d1746aba64f1060a3c

>---------------------------------------------------------------

commit 04569a95996bfb33091c39d1746aba64f1060a3c
Author: Joseph Wright <joseph at texdev.net>
Date:   Fri Apr 5 15:19:26 2024 +0100

    Use Lua-based tracking for indexed PDF objects


>---------------------------------------------------------------

04569a95996bfb33091c39d1746aba64f1060a3c
 l3kernel/l3pdf.dtx | 205 +++++++++++++++++++++++++++++++----------------------
 1 file changed, 121 insertions(+), 84 deletions(-)

diff --git a/l3kernel/l3pdf.dtx b/l3kernel/l3pdf.dtx
index 7a3c7ad9a..300d88dbb 100644
--- a/l3kernel/l3pdf.dtx
+++ b/l3kernel/l3pdf.dtx
@@ -379,10 +379,6 @@
 %   {\pdf_object_write:nnn, \pdf_object_write:nne, \pdf_object_write:nnx}
 % \begin{macro}{\pdf_object_ref:n}
 % \begin{macro}{\__kernel_pdf_object_id:n}
-% \begin{macro}{ltx.pdf.object_id}
-% \begin{macro}{\@@_object_record:nN}
-% \begin{macro}[EXP]{\@@_object_retrieve:n}
-% \begin{macro}[pTF,EXP]{\pdf_object_if_exist:n}
 %   Simple to do: all objects create a constant |int| so it is not a
 %   backend-specific name.
 %    \begin{macrocode}
@@ -410,9 +406,17 @@
   }
 %</tex>
 %    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\@@_object_record:nN}
+% \begin{macro}[EXP]{\@@_object_retrieve:n}
+% \begin{macro}{ltx.pdf.object_id}
 %   Object mappings are tracked in Lua for \LuaTeX{} as this makes retrieving
 %   them much easier; as a result, there is a split in approaches. In Lua we
-%   store values in a table indexed by name.
+%   store values in a table indexed by name. The Lua function here is set up
+%   to deal with both named and indexed objects: fits the Lua idiom well.
 %    \begin{macrocode}
 %<*lua>
 
@@ -420,16 +424,21 @@ local scan_int = token.scan_int
 local scan_string = token.scan_string
 local cprint = tex.cprint
 
-local @@_objects = {}
+local @@_objects_named = {}
+local @@_objects_indexed = {}
 
 luacmd('@@_object_record:nN', function()
   local name = scan_string()
   local n = scan_int()
-  @@_objects[name] = n
+  @@_objects_named[name] = n
 end,'protected','global')
 
-local function object_id(name)
-  return @@_objects[name] or 0
+local function object_id(name,index)
+  if index then
+    return @@_objects_indexed[name][index] or 0
+  else
+    return @@_objects_named[name] or 0
+  end
 end
 
 luacmd('@@_object_retrieve:n', function()
@@ -462,6 +471,12 @@ ltx.pdf.object_id = object_id
           { 0 }
       }
   }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \begin{macro}[pTF,EXP]{\pdf_object_if_exist:n}
+%    \begin{macrocode}
 \prg_new_conditional:Npnn \pdf_object_if_exist:n #1 { p , T , F , TF }
   {
     \int_compare:nNnTF { \@@_object_retrieve:n {#1} } = 0
@@ -470,120 +485,142 @@ ltx.pdf.object_id = object_id
   }
 %    \end{macrocode}
 % \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{variable}{\c_@@_object_block_size_int}
-%   Sets the block size used for managing indexed objects.
-%     \begin{macrocode}
-\int_const:Nn \c_@@_object_block_size_int { 10000 }
-%    \end{macrocode}
-% \end{variable}
 %
 % \begin{macro}{\pdf_object_new_indexed:nn}
-% \begin{macro}{\@@_object_new_indexed:Nn}
 % \begin{macro}{\pdf_object_write_indexed:nnnn, \pdf_object_write_indexed:nnne}
-% \begin{macro}{\@@_object_write_indexed:Nnnn}
 % \begin{macro}[EXP]{\pdf_object_ref_indexed:nn}
 % \begin{macro}[EXP]{\__kernel_pdf_object_id_indexed:nn}
-% \begin{macro}[EXP]{\@@_object_ref_indexed:Nn, \@@_object_id_indexed:Nn}
-% \begin{macro}[EXP]{\@@_object_indexed_split:nnN}
-%   Using indexed values is much the same, except we have to split up the
-%   value. As that's repetitive, we use a single auxiliary.
+%   Again we split between the common code and the macro- or Lua-based
+%   implementation. To make life easier for the Lua route, all of the
+%   potential expressions are expanded to braced numbers.
 %    \begin{macrocode}
 \cs_new_protected:Npn \pdf_object_new_indexed:nn #1#2
-  {
-    \@@_object_indexed_split:nnN {#1} {#2}
-      \@@_object_new_indexed:Nn
-  }
-\cs_new_protected:Npn \@@_object_new_indexed:Nn #1#2
   {
     \@@_backend_object_new:
-    \intarray_if_exist:NF #1
-      {
-        \intarray_new:Nn #1
-          \c_@@_object_block_size_int
-      }
-    \intarray_gset:Nnn #1 {#2} \g_@@_backend_object_int
+    \@@_object_record:neN {#1}
+      { \int_eval:n {#2} } \g_@@_backend_object_int
   }
-\cs_new_protected:Npn \pdf_object_write_indexed:nnnn #1#2#3#4
-  {
-    \@@_object_indexed_split:nnN {#1} {#2}
-      \@@_object_write_indexed:Nnnn
-        {#3} {#4}
-  }
-\cs_generate_variant:Nn \pdf_object_write_indexed:nnnn { nnne }
-\cs_new_protected:Npn \@@_object_write_indexed:Nnnn #1#2#3#4
+\cs_new_protected:Npn \pdf_object_write_indexed:nnn #1#2#3#4
   {
     \exp_args:Ne \@@_backend_object_write:nnn
-      { \intarray_item:Nn #1 {#2} }
-      {#3} {#4}
+      { \@@_object_retrieve:ne {#1} { \int_eval:n {#2} } } {#3} {#4}
     \bool_gset_true:N \g_@@_init_bool
   }
-\cs_new:Npn \pdf_object_ref_indexed:nn #1#2
-  {
-    \@@_object_indexed_split:nnN {#1} {#2}
-      \@@_object_ref_indexed:Nn
-  }
-\cs_new:Npn \@@_object_ref_indexed:Nn #1#2
+\cs_generate_variant:Nn \pdf_object_write_indexed:nnnn { nnne }
+\cs_new:Npn \pdf_object_ref_indexed:n #1#2
   {
     \exp_args:Ne \@@_backend_object_ref:n
-      {
-        \intarray_if_exist:NTF #1
-          { \intarray_item:Nn #1 {#2} }
-          { 0 }
-      }
+      { \@@_object_retrieve:ne {#1} { \int_eval:n {#2} } }
   }
 \cs_new:Npn \__kernel_pdf_object_id_indexed:nn #1#2
   {
-    \@@_object_indexed_split:nnN {#1} {#2}
-      \@@_object_id_indexed:Nn
+    \exp_args:Ne \@@_backend_object_id:n
+      { \@@_object_retrieve:ne {#1} { \int_eval:n {#2} } }
   }
-\cs_new:Npn \@@_object_id_indexed:Nn #1#2
+%</tex>
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\@@_object_record:nnN, \@@_object_record:neN}
+% \begin{macro}[EXP]{\@@_object_retrieve:nn}
+% \begin{macro}{\@@_object_record:NnN}
+% \begin{macro}[EXP]{\@@_object_retrieve:Nn}
+%   Again we split for Lua: the same idea as above but with nested tables.
+%   As we've arranged above that the \TeX{} code passes a braced number,
+%   we can use |tonumber(scan_string())| rather than |scan_int()|
+%   for the index.
+%    \begin{macrocode}
+%<*lua>
+
+luacmd('@@_object_record:nnN', function()
+  local name = scan_string()
+  local index = tonumber(scan_string())
+  local n = scan_int()
+  @@_objects_indexed[name] = @@_objects_indexed[name] or {}
+  @@_objects_indexed[name][index] = n
+end,'protected','global')
+
+luacmd('@@_object_retrieve:nn', function()
+  local name = scan_string()
+  local index = tonumber(scan_string())
+  return cprint(12,tostring(object_id(name,index)))
+end,'global')
+
+%</lua>
+%    \end{macrocode}
+% The non-Lua approach is to divide the range into blocks, and store in integer
+% arrays that can simulate dynamic assignment.
+%    \begin{macrocode}
+%<*tex>
+\sys_if_engine_luatex:F
   {
-    \exp_args:Ne \@@_backend_object_id:n
+    \cs_new_protected:Npn \@@_object_record:nnN #1#2#3
+      {
+        \use:e
+          {
+            \@@_object_record:NnN
+               \@@_object_index_split:nn {#1} {#2}
+               \exp_not:N #3
+          }
+      }
+    \cs_new_protected:Npn \@@_object_record:NnN #1#2#3
+      {
+        \intarray_if_exist:NF #1
+          { \intarray_new:Nn #1 \c_@@_object_block_size_int }
+        \intarray_gset:Nnn #1 {#2} #3
+      }
+    \cs_new:Npn \@@_object_retrieve:nn #1#2
+      {
+        \use:e
+          {
+            \exp_not:N \@@_object_retrieve:Nn
+              \@@_object_index_split:nn {#1} {#2}
+          }
+      }
+    \cs_new:Npn \@@_object_retrieve:Nn #1#2
       { \intarray_item:Nn #1 {#2} }
-  }
 %    \end{macrocode}
 %   As we want blocks to start from one, and within the block for the top value
 %   to be \enquote{in} the block, we do a little bit of manipulation. By shifting
 %   down by one, we keep the values \enquote{in} the block, then we adjust the
 %   block/index number to get back on track.
 %    \begin{macrocode}
-\cs_new:Npn \@@_object_indexed_split:nnN #1#2#3
-  {
-    \use:e
+    \cs_new:Npn \@@_object_index_split:nn #1#2
       {
-        \exp_not:N #3
-          \exp_not:c
-            {
-              g_@@_object_ #1 _
-              \int_eval:n
-                {
-                  \int_div_truncate:nn { #2 - 1 }
-                    \c_@@_object_block_size_int + 1
-                }
-              _intarray
-            }
+        \exp_not:c
+          {
+            g_@@_object_ #1 _
+            \int_eval:n
+              {
+                \int_div_truncate:nn { #2 - 1 }
+                  \c_@@_object_block_size_int + 1
+              }
+            _intarray
+          }
           {
             \int_eval:n
               { \int_mod:nn { #2 - 1 } \c_@@_object_block_size_int + 1 }
           }
       }
-  }
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
 % \end{macro}
 % \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
+% \begin{variable}{\c_@@_object_block_size_int}
+%   Sets the block size used for managing indexed objects.
+%    \begin{macrocode}
+    \int_const:Nn \c_@@_object_block_size_int { 10000 }
+  }
+%    \end{macrocode}
+% \end{variable}
+% \begin{macro}[EXP]{\@@_object_retrieve:ne}
+%   A common variant.
+%    \begin{macrocode}
+\cs_generate_variant:Nn \@@_object_record:nnN { ne }
+%    \end{macrocode}
 % \end{macro}
 %
 % \begin{macro}





More information about the latex3-commits mailing list.