3

Is it possible to create a single document which appears different when printed?

Not separate modes which typeset multiple documents per input TeX, but a single document which prints differently than its electronic version?

I know there are various OCG packages for LaTeX. Does something exist for ConTeXt?

My goal is to transform the first link into the second link when printed:

\definefallbackfamily   [mainface] [serif] [Symbola] [range={miscellaneoussymbolsandpictographs}]
\definefontfamily       [mainface] [serif] [DejaVu Serif]
\definefontfamily       [mainface] [sans]  [DejaVu Sans]
\definefontfamily       [mainface] [mono]  [DejaVu Sans Mono]

\setupbodyfont[mainface]

\definesymbol[link][\utfchar{"1F517}]

\def\raisedlink{%
    \tfxx%
    \setbox\scratchbox\hbox{\symbol[link]}%
    \raise0.5\dp\scratchbox\box\scratchbox%
}

\setupinteraction
    [state=start,
     style=,
     color=,
    ]

\useURL
    [web:contextElectronic]
    [https://github.com/contextgarden/context-mirror]
    []
    [{github.com/contextgarden\raisedlink}]

\useURL
    [web:contextPrint]
    [https://github.com/contextgarden/context-mirror]
    []
    [{github.com/contextgarden}]

\showallmakeup


\starttext
[\from[web:contextElectronic]]

[\from[web:contextPrint]]
\stoptext

* In the print version notice the lack of whitespace between the link and the closing bracket.

Kurt Pfeifle
  • 3,791
user19087
  • 819
  • There was a related question some time ago (Optionally colored links in ConTeXt) and no, OCG is not available in ConTeXt. I guess it would break PDF/A or PDF/X compatibility. – Henri Menke Dec 18 '18 at 21:10
  • @HenriMenke But the packages do work in LuaLaTeX? – user19087 Dec 20 '18 at 21:47
  • But LuaLaTeX is very different from ConTeXt. In principle you could implement OCG yourself by flushing the correct instruction to the PDF stream, similar to what the LaTeX packages do. – Henri Menke Dec 20 '18 at 23:21
  • Which PDF feature does ConTeXt hyperlinks: Answer using references.border use - can I hook into that? Also did a quick search for [context] + [ocg]|[hyperref]|[links]|[printing] and I don't think there are any other niche approaches. – user19087 Dec 21 '18 at 03:21
  • The references.border mechanism just uses the /Border field for /Link annotations. That is a different approach from OCG. You can find more about that in the Adobe PDF specification. – Henri Menke Dec 21 '18 at 03:51
  • I took a look at the Adobe PDF 1.7 specification. The only reference to layers I found was in relation to Optional Content Groups (OCG), 4.10. Which begs the question, does the answer below describing ConTeXt's viewerlayer mechanism make use of OCG? – user19087 Dec 21 '18 at 18:25
  • Next is section 8.4, annotations. The Border entry in PDF 1.0 allows rounded corners and border width, extended in PDF 1.1 with dash patterns. PDF 1.2 allows additional non-rectangle shapes (beveled, inset, underline) via a new Border Style (BS) entry. In PDF 1.5 a Border Effect (BE) entry allows blurring the border. – user19087 Dec 21 '18 at 18:31
  • Most interesting, beginning with PDF 1.2 all this can be replaced with appearance streams containing form XObjects describing the appearance of the annotation in various states: the Appearance (AP) and Appearance State (AS) entries. This mechanism should, in theory, allow complete control over the contents of the link annotation in various states: normal, print, mouse rollover, and mouse down, i.e. this could solve my question. – user19087 Dec 21 '18 at 18:31
  • One aspect I don't understand is how a link annotation border can be hidden for print while the link remains visible. The only reference to print visibility in section 8.4 was the "print" annotation flag (bit position 3) and the inverse "NoView" annotation flag (bit position 6). If set, the annotation is never printed. This includes the "Content" entry: text to be displayed for the annotation. – user19087 Dec 21 '18 at 18:31
  • Problem solved. Link annotations aren't markup annotations and so don't display the "Contents" entry. Therefore they can only be used to supplement standard page content (i.e. the URI, which will be always displayed, whether print or screen) by overlaying additional content as specified by the Border, BS, BE, AP, and AS entries. – user19087 Dec 21 '18 at 18:32
  • So I can theoretically use the AP entry to draw a link symbol after my URI keeping the "Print" and "NoView" flags unset to hide the symbol for print. But only if my URIs are not aligned flush-right - otherwise the symbol would extend past the alignment border. Alternatively I could put the symbol with the URI and use a shape annotation to hide it. Most interesting would be to use two free-text annotations, one with the screen-space URI and one with the print-space URI. They're absolutely positioned so aligning them would probably be tricky. – user19087 Dec 21 '18 at 18:34

2 Answers2

6

You can create layers which are only shown in the screen or print version of your document with the viewerlayer mechanism. Whether the content of the command appears in the printed output is controlled with the printable key.

enter image description here

You should be aware that many PDF viewer ignore the settings and display the argument of the command also on the screen and only Adobe Reader has a reliable output.

\usesymbols [fontawesome]

\defineviewerlayer [print] [state=stop,printable=yes]

\setupinteraction [state=start]

\useURL
  [context-github]
  [https://github.com/contextgarden/context-mirror]
  []
  [{github.com/contextgarden\viewerlayer[print]{\symbol[fontawesome][external-link]}}]

\starttext

\from[context-github]

\stoptext
Wolfgang Schuster
  • 9,400
  • 1
  • 16
  • 19
  • I admit that I'm having trouble finding a pdf viewer on linux that displays view layers properly. Every backend that I know of and have tested (xpdf, mupdf, poppler) never displays the view layer - neither in electronic form nor after printing. I'm wondering if it is possible to embed a javascript action to force correct display of the view layer. – user19087 Dec 20 '18 at 21:43
  • 2
    @user19087 That would imply that JavaScript is correctly implemented in those viewers which is unlikely at best. – Henri Menke Dec 20 '18 at 23:20
  • @user19087: Give up and forsake any hope of "embedding JavaScript actions to force correct display of view layer" when it comes to random PDF viewers, especially on Linux. On Linux there isn't any fully-fledged support for JavaScript in none of the available viewers (at least not in the open source ones). These mostly only support very basic mostly PDF-1.4 features. The same is true for macOS' Preview.app PDF viewer. These also do not support the correct display of layers (or Optional Content Groups, OCGs)... – Kurt Pfeifle Dec 21 '18 at 09:53
  • @user19087: ....The only Linux viewer to let you display layers (and toggle their visibility on/off by layer) is *Evince*. – Kurt Pfeifle Dec 21 '18 at 09:53
  • 1
    You're right. And I just discovered that \showallmakeup creates many layers (fontkern, glue, glyph, hbox, etc), each which can be hidden. Very nice. – user19087 Dec 22 '18 at 04:47
  • 1
    These are all the backends I've tested: foxit (wine), adobe (wine, 11.0.08 and DC.2019.010.20064), ghostscript, mupdf (same developers as ghostscript but a different engine), xpdf, and poppler (based on xpdf). They all support layers / optional content groups. Only foxit and adobe correctly display the print-only layer from this answer: hidden in the viewer, visible on paper. In all other backends the print-only layer is never visible, even when printed. – user19087 Dec 22 '18 at 04:56
  • 1
    In 2017 ghostscript added support for the /Print and /View keys of the Optional Content /Usage dictionary, i.e. the use of -dPrinted in gs -o output.pdf -sDEVICE=pdfwrite -dPrinted input.pdf should display the print-only layer, per to the documentation. From their repository you can see that poppler also checks the /Print and /View keys. – user19087 Dec 22 '18 at 04:56
  • 2
    Neither work with this answer so I'm considering filing a bug against ConTeXt. – user19087 Dec 22 '18 at 04:57
  • 1
    As for the frontends, I've tested zathura, xpdf, mupdf, gv, foxit, evince, apvlv, and adobe reader. Most frontends lack an interface for handling layers: zathura (there's actually a single line of stub code), mupdf, gv and apvlv. Since Mupdf doesn't allow printing it has no need to display print-only layers, which is why I haven't bothered seeing if checks the /Usage dictionary. – user19087 Dec 22 '18 at 04:58
  • 1
    And I think I'll continue this as a separate answer. – user19087 Dec 22 '18 at 17:17
  • @KurtPfeifle everything using Poppler should support this, e.g. Okular. – flying sheep Nov 06 '19 at 14:10
  • @flyingsheep: At the time I wrote my comment I also checked oKular (the KDE document and PDF viewer). It's also Poppler-based, but didn't support "layers" in PDF. May have changed since, but I cannot check it right now. – Kurt Pfeifle Nov 06 '19 at 14:18
  • Actually layer support exists since KDE Applications 15.11, released 3 years before your comment. – flying sheep Nov 06 '19 at 14:51
3

Even though viewerlayer layers are viewed independently they are typeset together. Content is positioned as though all layers are visible, and surrounding text doesn't shift according to the visibility of the layer.

\defineviewerlayer [print] [state=stop,printable=yes]

\starttext
\rightaligned{First flush-right sentence\viewerlayer[print]{... or is it}}

\rightaligned{Second flush-right sentence}
\stoptext

When this prints both sentences appear equally aligned to each other and the right edge. When viewed, the first sentence is aligned left of the second as its position is determined by the subsequent viewerlayer content even though that layer is hidden. To solve this you need to typeset all the affected content twice, assign each to one of two exclusive layers (i.e. print only vs view only), and then overlap these layers:

\defineviewerlayer [print] [state=stop,printable=yes]
\defineviewerlayer [view]  [state=start,printable=no]

\starttext
\rightaligned{\viewerlayer[view]{First flush-right sentence}\llap{\viewerlayer[print]{First flush-right sentence... or is it}}}

\rightaligned{Second flush-right sentence}
\stoptext

This, however, is where you start to encounter bugs. The following examples demonstrate problems ConTeXt 2018.12.18 has when typesetting documents with multiple viewerlayers. Primarily the layers do not seem properly closed, so that the layer subsumes all subsequent content. Documents tested in Adobe Reader 11.

When \showallmakeup is enabled, all content after \viewerlayer[print] belongs to that layer:

\defineviewerlayer[print][state=stop,printable=yes,]
\showallmakeup

\starttext
    \viewerlayer[print]{One} more.

    \samplefile{knuth}
\stoptext

The same problem as above, demonstrated with \start...stopviewerlayer rather than \viewerlayer:

\defineviewerlayer[print][state=stop,printable=yes,]
\showallmakeup

\starttext
    \startviewerlayer[print]
        And then:
    \stopviewerlayer

    \samplefile{knuth}
\stoptext

Rather than two independent layers, the print layer (along with other content) belongs to the view layer. So hiding the view layer hides all content in this document:

  • [view]
    • first
    • \samplefile{knuth}
    • [print]
      • second
\defineviewerlayer[print][state=stop,printable=yes,]
\defineviewerlayer[view][state=start,printable=no,]

\starttext
    \startviewerlayer[view]{first}

    \samplefile{knuth}

    \startviewerlayer[print]{second}
\stoptext

Nevermind, I forgot to close the blocks with \stopviewerlayer.

Additionally ConTeXt creates PDFs whose print-only layers are ignored by the ghostscript and poppler engines, even though those engines support such features. See comments to the accepted answer.

If you don't need such involved typesetting you might be better off using link annotations. See comments to the question:

Keep in mind that link annotations aren't markup annotations and so don't display the "Contents" entry. Therefore they can only be used to supplement standard page content (i.e. the URI, which will be always displayed, whether print or screen) by overlaying additional content as specified by the Border, BS, BE, AP, and AS entries... [as well as the link action].

Here are the (visible) link annotation features ConTeXt supports, per lpdf-ano.lua. For more information see section 8.4, Annotations, of the Adobe PDF 1.7 specification, also mentioned in the comments.

  • /Border

    ConTeXt only supports the PDF 1.0 fields. This is set to {0,0,0} if references.border isn't used; otherwise {0,0,0.5}. Can't be configured by the user.

    horizontal corner radius (PDF 1.0)
    vertical corder radius   (PDF 1.0)
    border width             (PDF 1.0)
    dash array               (PDF 1.1)
    
  • /C (color)

    This is the field set by references.border. ConTeXt only supports the three-entry version, DeviceRGB. You can use color names like "green" because of a ConTeXt-specific conversion.

  • /H (highlight; specific to link annotations)

    Set to N, no highlighting, if actions.highlight is False. This is what you usually see. Otherwise ConTeXt leaves this field empty and per the PDF specifications it defaults to I, invert - invert the contents of the annotation rectangle. I'm not sure how to set actions.highlight.

ConTeXt does not support or set the newer "Border Style" (BS, PDF 1.2), "Border Effect" (BE, PDF 1.5), Appearance (AP, PDF 1.2), or Appearance State (AS, PDF 1.2) fields.

The /F entry is a bitfield representing various flags. For link annotations ConTeXt appears to set /F to 4, or 0b100. This enables only the Print field, and should force the link annotation border to print when the page is printed for PDF/A compatibility. This doesn't happen - when printed the link annotation border is hidden - and I'm not sure why.

user19087
  • 819
  • Can you please post the bug you encountered with view layers on the mailing list? https://mailman.ntg.nl/mailman/listinfo/ntg-context – Henri Menke Dec 22 '18 at 21:16