olsak / OpTeX

OpTeX - LuaTeX format with extended Plain TeX macros
http://petr.olsak.net/optex/
35 stars 13 forks source link

Make luaotfload transparency work with its hooks #101

Closed vlasakm closed 1 year ago

vlasakm commented 2 years ago

Since we added new PDF resource management, transparent font settings through luaotfload were broken.

It was now possible to fix this thanks to new hooks in luaotfload. See https://github.com/latex3/luaotfload/pull/212.

I tested with https://github.com/vlasakm/optex-minim/blob/master/examples/optex-minim-pgf-test.tex, since that file mixes a lot of things (luaotfload transparency, optex transparency, minim metapost resources, pgf resources, optex macro resources, ...), but didn't do a lot of thorough testing.

vlasakm commented 2 years ago

I hope https://github.com/gucci-on-fleek/lua-widow-control/issues/39 can be resolved here as well, while at it. I have "draft" in https://github.com/vlasakm/OpTeX/commit/1b2070eebaa2dc527fcb87e7d5a73d73dcee6067.

vlasakm commented 1 year ago

Alright, https://github.com/olsak/OpTeX/pull/101/commits/1b2070eebaa2dc527fcb87e7d5a73d73dcee6067 is good for https://github.com/gucci-on-fleek/lua-widow-control/issues/39, so I pushed it and hope this PR is ready to go. What do you think @olsak?

olsak commented 1 year ago

cited from https://github.com/gucci-on-fleek/lua-widow-control/issues/39: "OpTeX: Cannot colour the first line of the page since OpTeX resets the colour there." I don't understand this. I am unable to create a minimal example which shows the problem.

gucci-on-fleek commented 1 year ago

@olsak

A messy example:

\fontfam[LM]

\directlua{
    callback.add_to_callback("pre_output_filter", function (head)
        for hlist in node.traverse_id(node.id("hlist"), head) do
            local colour = string.format(
                "\%.2f \%.2f \%.2f rg",
                1,
                math.random(),
                math.random()
            )

            local start_colour = node.new("whatsit", "pdf_colorstack")
            start_colour.stack = 0
            start_colour.command = 1
            start_colour.data = colour

            local end_colour = node.new("whatsit", "pdf_colorstack")
            end_colour.stack = 0
            end_colour.command = 2

            start_colour.next = hlist.list
            hlist.list = start_colour
            node.slide(hlist.list).next = end_colour
        end

        return head
    end, "test")
}

Hello!

Hello!

Hello!

\vfill\eject

Hello!

Hello!

Hello!

\bye

If we disassemble the PDF with qdf, you can see that OpTeX resets the text colour to black after the pdf_colorstack, thus overriding it.

%% Contents for page 1
%% Original object ID: 3 0
13 0 obj
<<
  /Length 14 0 R
>>
stream
0.68 0.73 0.66 rg
0 g
BT
/F37 9.96264 Tf
1 0 0 1 90.791 761.061 Tm [<003e00320048004800510035>]TJ
0 g 0 G
0.90 0.54 0.64 rg
1 0 0 1 90.791 749.106 Tm [<003e00320048004800510035>]TJ
0 g 0 G
0.90 0.93 0.96 rg
1 0 0 1 90.791 737.151 Tm [<003e00320048004800510035>]TJ
0 g 0 G
1 0 0 1 295.147 55.46 Tm [<0052>]TJ
ET
endstream
endobj
vlasakm commented 1 year ago

Well, in this case the fix can maybe be as simple as this:

diff --git a/optex/base/optex.lua b/optex/base/optex.lua
index bb67d7e..9e9c83a 100644
--- a/optex/base/optex.lua
+++ b/optex/base/optex.lua
@@ -652,10 +652,10 @@ end
 -- for this. See the definition of `pre_shipout_filter` for details on
 -- limitations.
 callback.add_to_callback("pre_shipout_filter", function(list)
-    -- By setting initial color to -1 we force initial setting of color on
-    -- every page. This is useful for transparently supporting other default
-    -- colors than black (although it has a price for each normal document).
-    local list = colorize(todirect(list), -1, -1, 0)
+    -- Each page has implicitly preset black color and no transparency, we tell
+    -- this to the colorize function so that it can take advantage of it and
+    -- not set it.
+    local list = colorize(todirect(list), 0, 0, 0)
     return tonode(list)
 end, "_colors")
 --

This setting of current_color = -1 is what forces the color setting at the start of the page. This is not necessary for black, since black is the default color, so it is possible to staart with current_color = 0. This helps with lua-widow-controls colorings, because nodes inserted by it don't have the color attribute set (thus color = 0), so when they appear at the start of the page the attribute mechanism will not recolor them.

But this doesn't save the general case, where the nodes could have color attributes set. Making lua-widow-control use the attributes seems cleaner to me (the color attaches to the content, wherever it ends up).

vlasakm commented 1 year ago

Hm, maybe the interface should change, so that lua-widow-control can set the attribute directly.

vlasakm commented 1 year ago

In the last commit I wrapped the hooks into luaotfload in pcall to ignore any errors. This is to make it possible to use new OpTeX with old luaotfload without the hooks. It should work, but I didn't test any old versions.