Skip to content
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

l3backend: dvips driver for draw does not properly handle scoped boxes/coffins #1504

Closed
jasperhabicht opened this issue Mar 11, 2024 · 8 comments
Assignees
Labels
bug Something isn't working l3backend Issues with the low-level backend code

Comments

@jasperhabicht
Copy link

It seems that the PS code generated by the l3draw driver/backend for dvips is not correct so that a stack underflow error occurs when boxes or coffins are scoped inside a l3draw environment. No error occurs if the box/coffin is not scoped.

Consider the following MWE (also see this issue on TeX.SX where some ideas regarding the reason for this issue have been mentioned already):

\documentclass[border=10pt]{standalone}
\usepackage{l3draw}

\begin{document}
    \ExplSyntaxOn
    \draw_begin:
    
        \draw_path_circle:nn { 0cm , 0cm } { 1cm }
        \draw_path_use_clear:n { stroke }
        
        \draw_scope_begin:
        \hbox_set:Nn \l_tmpa_box {foo}
        \draw_box_use:N \l_tmpa_box
        \draw_scope_end:
    
    \draw_end:
    \ExplSyntaxOff    
\end{document}

Steps

  1. run latex to produce a DVI file;
  2. run dvips to produce PS file;
  3. run Acrobat Distiller or some other software parsing the PS file.
@josephwright
Copy link
Member

Drat: I had hoped to avoid having to manually save/restore stuff as this more-or-less relies on internals of how dvips sets things up. But I can't think of another way around this other than using the approach pgf does - I guess I'll need to adjust.

@josephwright josephwright self-assigned this Mar 11, 2024
@josephwright josephwright added bug Something isn't working l3backend Issues with the low-level backend code labels Mar 11, 2024
josephwright added a commit that referenced this issue Mar 11, 2024
See #1504 - needs a bit of testing yet.
@davidcarlisle
Copy link
Member

davidcarlisle commented Mar 11, 2024

Not sure how safe it is but adding this to the example...

\cs_set_protected:Npn \__draw_backend_scope_begin:
{ \__draw_backend_literal:n {
    @endspecial ~ save ~ @beginspecial } }
\cs_set_protected:Npn \__draw_backend_scope_end:
  { \__draw_backend_literal:n { @endspecial ~ restore ~ @beginspecial} }

produces

image

dvisvgm also manages to understand this dvips syntax enough and the resulting svg looks like

image

@josephwright
Copy link
Member

@davidcarlisle Your idea and my original approach to the box insertion share a common issue. By issuing @endspecial, a scope is closed. That means that if a user has a setting before the box, e.g. a transformation or colour change, it would not apply after the box. For example, before the change I've commited,

\documentclass[border=10pt]{standalone}
\usepackage{l3draw}
\begin{document}
\ExplSyntaxOn
  \draw_begin:
    \color_select:n { red }
    \draw_path_circle:nn { 0cm , 0cm } { 1cm }
    \draw_path_use_clear:n { stroke }
    \hbox_set:Nn \l_tmpa_box {foo}
    \draw_box_use:N \l_tmpa_box
    \draw_path_circle:nn { 0cm , 0cm } { 2cm }
    \draw_path_use_clear:n { stroke }
  \draw_end:
\ExplSyntaxOff    
\end{document}

gives the wrong result with dvips. So I think a change is needed: I'll make some more notes in the sources and add a test or two.

@josephwright
Copy link
Member

I think things are OK now - testing suggests so.

@davidcarlisle
Copy link
Member

I saw as I posted that you'd just done a checkin saving and restoring explicitly (which looks cleaner anyway than relying on dvips output quite so much). but I'm surprised it closes a scope if used as suggested. The idea was you'd end up with

@beginspecial % from dvips
@endspecial,   % from the \special content
save                % from the \special content
@beginspecial % from the \special content
@endspecial,  % from dvips

so the save is in the outer context and the two empty scopes do nothing, then you do the same wtih restore so following text should be in the original scope.

@josephwright
Copy link
Member

I meant that if you end up with for example

@beginspecial % from start-of-picture
1.0 0.0 0.0 TeXcolorrgb % from a color
@endspecial,   % from the \special content
save                % from the \special content
@beginspecial % from the \special content
...                      % Content here
@endspecial,  % from dvips

then the content will come out black not red. As a concrete example, using dvips try

\documentclass{article}
\usepackage{l3draw}
\begin{document}
\ExplSyntaxOn
\cs_set_protected:Npn \__draw_backend_scope_begin:
{ \__draw_backend_literal:n {
    @endspecial ~ save ~ @beginspecial } }
\cs_set_protected:Npn \__draw_backend_scope_end:
  { \__draw_backend_literal:n { @endspecial ~ restore ~ @beginspecial} }
\draw_begin:
  \color_select:n { red }
  \draw_scope_begin:
  \draw_scope_end:
  \draw_path_moveto:n { 0cm, 0cm }
  \draw_path_lineto:n { 10cm, 0cm }
  \draw_path_moveto:n { 5cm, 0cm }
  \draw_path_lineto:n { 5cm , 5cm }
  \draw_path_use_clear:n { stroke }
\draw_end:
\ExplSyntaxOff    
\end{document}

with and without the lines commented. (You also see the line thickness revert to the one not set by l3draw.)

@josephwright
Copy link
Member

@davidcarlisle BTW, dvips doesn't add @beginspecial automatically, that comes from the \draw_begin: implementation.

@davidcarlisle
Copy link
Member

ah if you get stuf between the begin and end that would be bad:, agreed:-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working l3backend Issues with the low-level backend code
Projects
None yet
Development

No branches or pull requests

3 participants