pgf-tikz / pgf

A Portable Graphic Format for TeX
https://pgf-tikz.github.io/
1.15k stars 109 forks source link

pattern=Lines[...] renders very differently depending on the PDF viewer #1180

Open fpom opened 2 years ago

fpom commented 2 years ago

Brief outline of the bug

When using pattern=Lines[...] to fill a node, I get significantly different results depending on the PDF viewer. Here are screenshots of renderings of the PDF from the MWE, compiled with pdfLaTeX, and annotated by the PDF viewer that rendered them:

Firefox and Inkscape draw dashed lines: cap-firefox cap-inkscape-edit

In its preview window, Inkscape draws continuous lines: cap-inkscape-preview

Foxit-reader draw almost continuous lines with alignment problems: cap-foxit-reader

Ghostscript fails to align the lines: cap-ghostscript

The award of worst rendering goes to LibreOffice draw: cap-libreoffice-draw

Finally, xreader and evince draw what I was expecting: cap-xreader-evince

I'm not sure this is a bug of PGF/TikZ, but considering the renderings diversity, there is at least a portability issue.

Minimal working example (MWE)

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{patterns,patterns.meta}

\tikzstyle{hash}=[minimum size=3cm,draw]
\tikzstyle{left}=[hash,
  pattern={Lines[angle=45,distance=5pt,line width=.6pt]},
  pattern color=red!50!black]
\tikzstyle{right}=[hash,
  pattern={Lines[angle=-45,distance=5pt,line width=.6pt]},
  pattern color=blue!50!black]

\begin{document}

\begin{tikzpicture}
  \node[left] at (0,0) {};
  \node[right] at (1,0) {};
\end{tikzpicture}

\end{document}
ilayn commented 2 years ago

I am not sure about the PGF's part in this but note that not all viewers fully implement the PDF spec. Or alternatively they implement different versions of PDF. On top of that, certain apps emphasize/test/QA of certain functions more than the other so this is a very typical problem in PDF ecosystem and not necessarily the innocent PDFTeX.

There are many criticisms about PDF features that are prone to be misused by bad actors especially trying to be more interactive which I do agree partially. Hence some features are even not supported by certain apps. If you need portability, you must use Adobe. That is the only fully PDF compliant app by definition.

hmenke commented 2 years ago

Duplicate of https://github.com/pgf-tikz/pgf/issues/850

muzimuzhi commented 1 year ago

For the FireFox case, I think it's caused by the beneath pdf.js library, in which it can't correctly render patterns with negative bounding box coordinates. Any applications or extensions that relies on pdf.js are affected. See https://github.com/mozilla/pdf.js/issues/16038.

Currently in pgf-tikz, patterns like Lines defined in library patterns.meta always have their bounding boxes centered at (0,0), thus will eventually write sth like /BBox [ -1.49442 -1.49442 1.49442 1.49442 ] to pdf. Therefore one possible workaround (for pdf.js) is to define variant patterns that use all non-negative bounding box coordinates.

Below is an example defining pattern LinesX. It's the same as the dvisvgm-gh228.tex.zip I attached to https://github.com/mozilla/pdf.js/issues/16038.

\documentclass[margin=5pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{patterns.meta}

\makeatletter
% a new pattern LinesX based on Lines but has bbox coordinates all non-negative
% - Lines  creates `/Bbox [-a -b a b]` and drawing `-a 0 m a 0 l`
% - LinesX creates `/Bbox [0 0 2a ab]` and drawing `0 0 m 2a 0 l 0 2b m 2a ab l`
\pgfdeclarepattern{
  name=LinesX,
  parameters={
      \pgfkeysvalueof{/pgf/pattern keys/distance},
      \pgfkeysvalueof{/pgf/pattern keys/angle},
      \pgfkeysvalueof{/pgf/pattern keys/xshift},
      \pgfkeysvalueof{/pgf/pattern keys/yshift},
      \pgfkeysvalueof{/pgf/pattern keys/line width},
  },
  bottom left={%
    \pgfpointorigin
  },
  top right={%
    \pgfpoint
      {\pgfkeysvalueof{/pgf/pattern keys/distance}}%
      {\pgfkeysvalueof{/pgf/pattern keys/distance}}},
  tile size={%
    \pgfpoint
      {\pgfkeysvalueof{/pgf/pattern keys/distance}}%
      {\pgfkeysvalueof{/pgf/pattern keys/distance}}},
  tile transformation={%
    \pgftransformshift{%
      \pgfpoint
        {\pgfkeysvalueof{/pgf/pattern keys/xshift}}%
        {\pgfkeysvalueof{/pgf/pattern keys/yshift}}}%
    \pgftransformrotate{\pgfkeysvalueof{/pgf/pattern keys/angle}}},
  defaults={
    distance/.initial=3pt,
    angle/.initial=0,
    xshift/.initial=0pt,
    yshift/.initial=0pt,
    line width/.initial=\the\pgflinewidth,
  },
  code={%
    \pgfsetlinewidth{\pgfkeysvalueof{/pgf/pattern keys/line width}}%
    % half line at the bottom (y=0pt), due to clipping
    \pgfpathmoveto{\pgfpointorigin}%
    \pgfpathlineto{\pgfpoint{\pgfkeysvalueof{/pgf/pattern keys/distance}}{0pt}}%
    % half line at the top (y=/pgf/pattern keys/distance)
    \pgfpathmoveto{\pgfpoint{0pt}{\pgfkeysvalueof{/pgf/pattern keys/distance}}}%
    \pgfpathlineto{\pgfpoint{\pgfkeysvalueof{/pgf/pattern keys/distance}}{\pgfkeysvalueof{/pgf/pattern keys/distance}}}%
    \pgfusepath{stroke}%
  },
}
\makeatother

\begin{document}
\begin{tikzpicture}[pattern color=blue]
  \draw[pattern={Lines}]  (0,0)   rectangle  (1,1);
  \draw[pattern={LinesX}] (1.2,0) rectangle +(1,1);
\end{tikzpicture}
\end{document}
marco-c commented 2 months ago

This should soon be rendered correctly in Firefox, as https://github.com/mozilla/pdf.js/issues/16038 was fixed.