# ConTeXt: Replace PDF Content During Printing

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]

\tfxx%
\raise0.5\dp\scratchbox\box\scratchbox%
}

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

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

\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.

• 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 3: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 3:51

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.

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]
[]

\starttext

\from[context-github]

\stoptext

• @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
• 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 4:47
• 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 4:56
• 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 4:56
• Neither work with this answer so I'm considering filing a bug against ConTeXt. – user19087 Dec 22 '18 at 4:57

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.