-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle color using attributes #57
Conversation
\_else \_xdef\_currentcolor{#1}\_colorstackset\_currentcolor \_fi | ||
} | ||
\_def\_pdfblackcolor{0 g 0 G} | ||
\_edef\_currentcolor{\_pdfblackcolor} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we keep this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example
\_def\_pdfblackcolor{0 g}
\_def\_currentcolor{\_trycs{_color:\_the\_colorattr}{\_pdfblackcolor}}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the current state, even with your suggestion added, the old (documented) idiom \let\yourmacro=\_currentcolor
-> \_setcolor\yourmacro
wouldn't really work - \_setcolor
expects now something like {0}gG
, while \cs{_color:\_the\_colorattr}
would expand to 0 g
.
I think that with the power of grouping, the concept of saving colors is not needed. But I am not sure about the right interface if it has to be kept.
\_def \_draftbox #1{\_setbox0=\_hbox{\_setgreycolor{.8}#1}% | ||
\_kern.5\_vsize \_kern\_voffset \_kern4.5\_wd0 | ||
\_hbox to0pt{\_kern.5\_xhsize \_kern\_hoffset \_kern-2\_wd0 | ||
\_pdfsave \_pdfrotate{55}\_pdfscale{10}{10}% | ||
\_hbox to0pt{\_localcolor\_setgreycolor{.8}\_box0\_hss}% | ||
\_hbox to0pt{\_box0\_hss}% | ||
\_pdfrestore | ||
\_hss}% |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be improved?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I plan to re-implement \draftbox
to keep zero vertical dimensions and do \gtoksapp\_pgbackground
instead \_pgbackground=
. Moreover, I add a recommendation to the doc.: use \gtoksapp
or \gtokspre
if you have your own background and keep vertical size zero. Then you can have more layers of the page background.
Example how this works: \fontfam[lm]
\onlyrgb
black {\Red \hbox{m\Brown ixe}d {\Green\hbox{green}} red} black
\bye Before
After:
|
Thank you for very interesting request. I need more time to thing and test it, because it in not fully backward compatible. But it seem that it brings more advantages than disadvantages. Maybe, several weeks (months?) we will have it as alternative branch... |
In 8c40acd I moved a lot of things to TeX side. There seems to be no measurable performance penalty. And we can have nice interaction with This for example works as expected:
Although I would much rather see I chose to break compatibility with LuaTeX itself only uses stroke color for rules that have width or height+depth smaller than 1 bp. So in theory, if we change stroke color only for those rules and literals that may use stroke colors, we save a lot of color switching. In practice the calculated "width" and "height" dimensions of rule, used by For example for
EDIT: Forgot about |
Still haven't implemented |
Until you have the time to get back to this (no need to hurry!), this is what I now think of the raised points:
|
I did it in the end, but I still think it may not be necessary along with as with |
We can also hook into E.g. the following works as expected (sometimes, see below):
The disadvantage is, that to set this callback Another problem is, that Also it may be desirable to handle transparency using attributes as well (or we can let By the way, |
We agreed with @olsak to instead transform the last three commits (generic pre-shipout injector, transparency, font outlines) into OpTeX tricks. And also decided against more thorough management of "ExtGStates". Playing with it more, I think that OpTeX tricks is a good place for "generic" attribute handling and its applications (transparency and font outlines). They are just examples of what is possible with the new hooks (the tricks would require no change in OpTeX). But I realized that the ExtGState management I devised is pretty much what PGF/TikZ already does. I think its worth to do this right. (See #60, #61.) Will transform to OpTeX tricks (in this pull request) according to how #60 and #61 go. For reference this is the code I used for testing (both cases - with and without TikZ - are of course interesting for testing). \fontfam[lm]
\load[tikz]
\_addto\_byehook{\_the\_cs{pgfutil@everybye}}
a{\transparency{.5}b{\transparency{.2}c}b}a
{\Red a{A\outlinefont{.1}B\pdfliteral{0 1 0 RG}\outlinefont{.3}B}a}
\inoval[\shadow=3]{abc}
\tikzpicture[line width=1ex]
\draw (0,0) -- (3,1);
\filldraw [fill=yellow!80!black,draw opacity=0.5] (1,0) rectangle (2,1);
\endtikzpicture
\vfil\break
\slides
\slideshow
\sec A
\layers 3
{\pshow2 Second text.} {\pshow3 Third text.} {\pshow1 First text.}
\endlayers
* a \pg+
* b \pg+
* c \pg+
* d
\bye |
OK. Note that #60 was accepted to the master branch. |
This will be easier to read and would be required for other cases like transparencies, so it is probably better to be consistent.
efc05d3
to
0657980
Compare
Sorry, for not yet converting the above into OpTeX trick(s). Apart from needing to check the PDF spec, there is a problem. The code I previously pushed to this branch benefited from the already present local declarations in local node_id = node.id
local glyph_id = node_id("glyph")
local rule_id = node_id("rule")
local glue_id = node_id("glue")
local hlist_id = node_id("hlist")
local vlist_id = node_id("vlist")
local disc_id = node_id("disc")
local token_getmacro = token.get_macro
local direct = node.direct
local todirect = direct.todirect
local tonode = direct.tonode
local getfield = direct.getfield
local setfield = direct.setfield
local getlist = direct.getlist
local setlist = direct.setlist
local getleader = direct.getleader
local getattribute = direct.get_attribute
local insertbefore = direct.insert_before
local copy = direct.copy
local traverse = direct.traverse
local pdf_base_literal = direct.new("whatsit", "pdf_literal")
setfield(pdf_base_literal, "mode", 2) -- direct mode
local function pdfliteral(str)
local literal = copy(pdf_base_literal)
setfield(literal, "data", str)
return literal
end
local function create_pre_shipout_injector(attribute, default, namespace)
local current
local function injector(head)
for n, id, subtype in traverse(head) do
if id == hlist_id or id == vlist_id then
-- nested list, just recurse
setlist(n, injector(getlist(n)))
elseif id == disc_id then
-- only replace part is interesting at this point
local replace = getfield(n, "replace")
if replace then
setfield(n, "replace", injector(replace))
end
elseif id == glyph_id or id == rule_id
or (id == glue_id and getleader(n)) then
local new = getattribute(n, attribute) or 0
if new ~= current then
local literal = token_getmacro(namespace..new)
head = insertbefore(head, n, pdfliteral(literal))
current = new
end
end
end
return head
end
return function(list)
current = default
return tonode(injector(todirect(list)))
end
end
callback.add_to_callback(
"pre_shipout_filter",
create_pre_shipout_injector(registernumber("_transpattr"), 0, "_transp:"),
"_transp"
)
callback.add_to_callback(
"pre_shipout_filter",
create_pre_shipout_injector(registernumber("_fntoutattr"), 0, "_fntout:"),
"_fntout"
) While the local assignments can be merged into one line, that doesn't help the readability much.. Still the @olsak, how should I proceed? |
I hope that it is possible to create a global function |
In the end I changed the interface a little bit. @olsak I am open to your suggestions or improvements. Feel free to delete documentation if excessive or notify me about missing explanations. As far as I know this Pull request should as a whole more or less work as expected. The exceptions are:
|
I added rebased (ready to be merged without conflicts) variant of this branch to my fork: master...vlasakm:attributecolor-rebased It is squashed into just 7 functionally distinct and hopefully atomic commits. @olsak I suggest that instead of eventually merging this Pull request (which would require me force pushing this branch and as far as I can tell deleting the visual and correct history seen above), you merge/rebase manually instead with something like:
If you merge #62 first, then I will force-push the |
For OpTeX trick 64 I have the following image, but it needs adjustments for your page. You may be better off creating the image from the source below.
|
Please, don't make any new changes in this issue. I will try to merge it using |
Ok, if this is something that can be incorporated into the 7 remaining commits I can still edit it retroactively. Note that because you will do a "manual merge/rebase"' then Github won't know that this Pull request should be closed. One of us will have to do it manually (with "Close" not "Merge"). |
@olsak Sorry, but I had to push a bug fix. It shouldn't hurt in this branch, because it won't be merged. I don't know whether you already pulled
|
I used the same code from your |
This is an attempt to get rid of
\pdfcolorstack
+\aftergroup
mix along with global / local colors concept. The implementation handles color using on LuaTeX's attributes. For some motivation and information about differences of attribtes vs colorstacks/literals see the documentation added tooptex.lua
in this pull request.This is sadly a big and breaking change. Not that the old behaviour couldn't somehow be emulated, but perhaps it would be beneficial to do it "the right way". This means that we should first define what is the right and expected behaviour when color is involved.
This pull request colors content (text, rules, etc.) based on its attributes. Attributes stay frozen, like the font property of char/glyph nodes. No boxing and unboxing changes that. Nodes (what becomes out of characters, boxes, etc) get assigned attributes at their creation, which means that there are edge cases like the horizontal lists created by linebreaking, which get attributes that are active at the end of paragraph. This is no problem for this implementation, because we only care about nodes which have relation to colors (glyphs, rules, pdf literals).
One can think of it like this:
Is it for example expected, that an insert created when "\Green" is set, will be green? I don't think so, that is why this implementation still forces color reset at some places (instead of
\_ensureblack
this is called\_resetcolor
).I chose to not implement coloring of leaders. I tried, but I don't think its worth the complexity. Without handling leaders the whole coloring is so consise and easy to understand. Note that despite that perhaps all reasonable uses of
\leaders
work (for example\.tecky
from CTUstyle3).Like with colorstacks, one can also set a "default" color. So the main text color doesn't have to black. This is very easy to support, but is maybe non-obvious and maybe we would be better without it. (But I think OpTeX currently supports it with
\_pdfblackcolor
). If we keep this we need to somewhere draw line between what is\Black
and what is "default color".Do we need to support
\_currentcolor
? I currently didn't implement it. It would be kind of painful, because it is the TeX/Lua interfacing again. I think that with the right grouping mindset, it isn't needed, but maybe I am wrong.Should
\_setcolor
be implemented in Lua, or be perhaps more like:Handling of general inserts and footnotes has to be decided. I currently reset the color to black at the start of each insert.
Perhaps it would be worth to devise better mechanism for Lua scripts in OpTeX.
define_lua_command
is how we let TeX call into Lua, because it allows us to create "pseudoprimitives". Each feature could then be implemented in separate file and exposed to Lua only using this. The Lua code could even be inlined to.opm
files, and still have no cost at run time (only at format creation time). I don't know a nice way to make\public
variants of these Lua primtives.Currently the implementation hooks itself into output routine by redefining
\shipout
. Onether possibility is to define our preshipout callback, which could be used by coloring (this is how it is done in LaTeX and essentially also in ConTeXt).PDF form XObjects are problematic because of
\immediate
. Currently everyone has to first\colorizebox
and then use\pdfxform
.I still have to check handling of discretionary nodes (I think that they don't participate much in this stage).
Maybe we can save some color switches/checks -- for example images are(?) not influenced by color setting. However, this increases complexity and probably doesn't save anything in real scenarios.
Surprisingly for documents I tried in the end everything seemed to work correctly. But that is because usual documents don't use nonlocal colors, colored inserts and a lot of boxing/unboxing.
All in all, these are the advantages:
Disadvantages:
[1]: I tested my thesis (mediocre use of colors) and optex-doc.tex (more substantial use of colors):
Thesis:
Benchmark 1:
mmoptex vlasami6-bp.tex
(with attributes)Benchmark 2:
mmoptex vlasami6-bp.tex
(with colorstacks)OpTeX documentation:
Benchmark 3:
mmoptex optex-doc.tex
(with attributes)Benchmark 4:
mmoptex optex-doc.tex
(without attributes)The time loss seems to stay under 2 % (0.8 % for thesis, 1.5 % for documentation). What surprised me was the size shrink, even for compressed files (1.3 % for thesis, 0.7 % for documentation). I think that this trade-off alone may be worth.
This diff snippet shows how we decrease the file size:
Redundant settings of color are eliminated and this allows LuaTeX to sometimes merge following texts into one text object with kernings, instead of having to set new text matrix.
Things to sort out before merging:
\Black
vs default color?colors.opm
? Better Lua mechanism?\_setcolor
in Lua or TeX?More to do:
optex.lua
.`
seems to be the problem.I am surely missing something, but why is the nested
\_hbox to0pt
needed in\draftbox
?I am certain that this brain dump is somewhere wrong and I may have not explained well something that now seems obvious to me. Please comment with anything that comes to mind.
@olsak I would be grateful for your review of the TeX parts and suggestions on above raised points. I am available to you here or privately. I thought that for code review/updates we could use Github with its review features and add more commits to pull requests (either by me or you). This way we could enhance this branch with small changes and then squash the commits for nicer git history. But only if you are really interested in this feature at all, after really looking into it I can see reasoning for both approaches (colorstacks and attributes). Let me know.