%\iffalse meta-comment % % Copyright (C) Walter Daems % % This work may be distributed and/or modified under the conditions of % the LaTeX Project Public License, either version 1.3 of this license % or (at your option) any later version. The latest version of this % license is in: % % http://www.latex-project.org/lppl.txt % % and version 1.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Walter Daems. % % \fi % % \iffalse % %<@@=beamerreveal> %<*driver> \NeedsTeXFormat{LaTeX2e} \ProvidesFile{beamer-reveal.dtx} [2025-12-30 v1.00 .dtx skeleton file] % %<*reveal> \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{beamer-reveal} [2025-12-30 v1.00 .dtx skeleton file] \RequirePackage{expl3} \RequirePackage{xparse} \RequirePackage{tikz} \usetikzlibrary{calc} % %<*driver> \documentclass[a4paper,10pt]{ltxdoc} \usepackage{geometry} % In the preamble \renewenvironment{macro}[1]{% \par\addvspace{1.0\baselineskip}% \begingroup % Typeset the name as a paragraph heading \hspace*{-0.75cm} \begin{minipage}{\textwidth} \rule{3cm}{1pt}\\ \hspace*{1ex}\texttt{\string#1}\\ \rule[0.25\baselineskip]{3cm}{1pt} \end{minipage} % Index it: \SpecialMainIndex{#1}% \endgroup \ignorespaces }{% \par\addvspace{0.5\baselineskip}% } \usepackage{newpxtext,newpxmath} \def\fileversion{v1.00} \def\filedate{2025-12-30} \usepackage{makeidx} \usepackage{amsmath} \usepackage{alltt} \usepackage{booktabs} \usepackage{metalogo} \usepackage{enumitem} \usepackage{tikz} \usetikzlibrary{arrows} \tikzset{>=stealth'} \IfFileExists{tocbibind.sty}{\usepackage{tocbibind}}{} \IfFileExists{hyperref.sty}{ \usepackage[bookmarksopen]{hyperref} \hypersetup{citecolor=blue,linkcolor=blue} \hypersetup{hypertexnames=false} }{} \EnableCrossrefs \CodelineIndex \RecordChanges \newlist{arguments}{description}{2} \setlist[arguments]{leftmargin=3em,topsep=0pt,itemsep=0.5ex,parsep=0pt} \newlist{options}{description}{2} \setlist[options]{leftmargin=10em,style=nextline,topsep=0pt,itemsep=0.5ex,parsep=0pt} \newcommand\beamerreveal{\textsc{beamer-reveal}} \newcommand\beamer{\textsc{beamer}} \newcommand\Beamer{\textsc{Beamer}} \setlist[itemize]{itemsep=0.5ex,topsep=0pt,parsep=0pt} \setlist[enumerate]{itemsep=0.5ex,topsep=0pt,parsep=0pt} \begin{document} \DocInput{beamer-reveal.dtx} \end{document} % % \fi % % \changes{v0.80}{2025/12/21}{\@ Alpha 1 embryonic demo version} % \changes{v0.85}{2025/12/21}{\@ Alpha 2 tested by Walter, functional % on Linux} % \changes{v0.90}{2025/12/24}{\@ Beta 1 tested by Paul, not % functional on MS-Windows} % \changes{v0.95}{2025/12/17}{\@ Beta 2 tested by Paul, functional on MS-Windows} % \changes{v1.0}{2025/12/27}{\@ First appearance on CTAN} % \DoNotIndex{\group,\_,\AddToHook,\bool,\box,\c,\cs,\dim,\ExplSyntaxOn,\ExplSyntaxOff,\ProcessKeyOptions,\beamer@frametitle,\insertpagenumber,\insertframenumber,\insertoverlaynumber,\inserttitle,\int,\iow,\keys,\message,\msg,\newdimen,\only,\pageheight,\pagewidth,\path,\pgfmathsetmacro,\secname,\subsecname,\textcolor,\sys,\RequirePackage,\fp,\tl,\AtEndDocument,\newcommand,\newenvironment,\begin,\bfseries,\draw,\clip,\else,\fi,\if,\fill,\filldraw,\ifthenelse,\ifx,\textwidth,\node,\\,\@empty,\@tempdima,\@tempdimb,\@tempswatrue,\{,\},\ ,\bf,\BODY,\break,\Alph,\and,\define@key,\color,\dx,\dy,\g,\gdef,\hbox,\tiny,\scriptsize,\footnotesize,\small,\normalsize,\large,\Large,\LARGE,\huge,\Huge,\l,\LaTeX,\let,\p@,\relax,\renewcommand,\Requirepackage,\textbf,\textsf,\texttt,\textbackslash,\vspace,\hspace,\hfill,\hskip,\vskip,\hline,\vrule,\typeout,\usebox,\end,\paperheight,\paperwidth,\par,\NewDocumentCommand,\seq} % \setlength{\parindent}{0em} % \addtolength{\parskip}{0.5\baselineskip} % % \title{\beamerreveal} % \author{Walter Daems (|walter.daems@uantwerpen.be|)} % \date{Release \filedate{} --- \fileversion{}} % \newgeometry{left=3cm,right=2cm,top=2cm,bottom=2.5cm} % \maketitle % % \section{Introduction} % % \Beamer{} \cite{beamer} is a very powerful and convenient document class to create % presentations and slides. % However, integrating multimedia in it, is still a bit of a faff. % On one side you have the integrated |multimedia| facility of \beamer{} \cite{beamer} % and on the other side the |movie15| \cite{movie15} and |media9| % \cite{media9} packages. But unless you use the stock acrobat reader on % Microsoft Windows, these things barely work, if at all. % % Next to this \LaTeX{} ecosystem for slides, you have the reveal-js framework, that allows easy % integration of multimedia content. Why not combine both worlds? With that I mean: % \begin{itemize} % \item make your slides in \beamer{}, using all the nice packages that % come with \LaTeX{}, % \item include any browser-compatible multimedia content you'd like, % even generate some \LaTeX{} animations, % \item convert that presentation to the reveal.js framework. % \end{itemize} % That's exactly what this package does. % % \section{Rationale} % % Let's talk about the elephant in the room: why not work in the reveal % framework directly? I see two reasons: % \begin{itemize} % \item It avoids a new learning curve, allowing you to continue to % build on your \beamer{} expertise. % \item It avoids that you have to convert your thousands of slides % into a new format. % \end{itemize} % For me, those are all the reasons I need. % % \section{Synopsis} % % Figure~\ref{fig:flow} shows the overall flow. You start by making % slides (frames) the usual way using the |beamer| class. Your % source file (|slides.tex|) uses the package |beamer-reveal.sty| and references the % multimedia files of your choice. These multimedia files % (e.g. videos) can be super-imposed on any slide you like. % Your favorite \LaTeX-compiler typesets your slides to PDF and % produces an auxiliary |.rvl|-file containing extra information for % the conversion script. % The conversion script |beamer-reveal.pl| fuses the PDF and the % auxiliary file into a reveal.js presentation, using the templates % provided by the \beamerreveal{} package. In fact, this is done % by converting your slides to |JPG| format and using them as the % background on the \textsc{reveal}-slides. The multimedia content % appears as HTML5 elements on that background.\\ % You then use your favorite browser as your viewer instead of the % good old PDF reader. % \begin{figure} % \centering % \begin{tikzpicture} % [scale=0.7,transform shape, % doc/.style={rectangle,fill=black!10,align=center,minimum % width=2cm,minimum height=2cm}, % tool/.style={rectangle,draw,align=center}] % \draw (8.5,3.5) rectangle (12.5,5); % \draw[dotted,->] (9,4.5) -- (10,4.5) node[right] {``references''}; % \draw[->] (9,4) -- (10,4) node[right] {data flow}; % \node [doc] (slides) at (-3,0) {|slides.tex|\\\footnotesize(source file)}; % \node [tool] (latex) at (0,0) {\LaTeX{}\\\footnotesize(compiler)}; % \node [doc] (class) at (0,3) {|beamer.cls|\\\footnotesize(class)}; % \node [doc] (package) at (0,-4) {|beamer-|\\|reveal.sty|\\\footnotesize(package)}; % \node [doc] (pdf) at (4,1.25) {|slides.pdf|\\\footnotesize(PDF-file)}; % \node [doc] (rvl) at (4,-1.25) {|slides.rvl|\\\footnotesize(reveal-file)}; % \node [tool] (script) at (8,0) {|beamer-reveal.pl|\\\footnotesize(script)}; % \node [doc] (reveal) at (12,0) {|slides.html|\\\footnotesize(reveal.js website)}; % \node [doc] (template) at (8,-4) {beamer-reveal-\\templates}; % \node [doc] (mm) at (6,4) {Multimedia\\files}; % \draw[->] (slides) -- (latex); % \draw[->,dotted] (slides) -- (class); % \draw[->,dotted] (slides) -- (package); % \draw[->,dotted] (slides) -- (mm); % \draw[->,dotted] (reveal) -- (mm); % \draw[->,dotted] (pdf) -- (mm); % \draw[->,dotted] (rvl.north east) -- (mm); % \draw[->] (class) -- (latex); % \draw[->] (package) -- (latex); % \draw[->] (latex) edge[out=0,in=180] (pdf); % \draw[->] (latex) edge[out=0,in=180] (rvl); % \draw[->] (pdf) edge[out=0,in=180] (script); % \draw[->] (rvl) edge[out=0,in=180] (script); % \draw[->] (template) -- (script); % \draw[->] (script) -- (reveal); % \draw[thick,dashdotted] (-2,-5.5) coordinate(bl) -- (10,-5.5) -- (10,1) -- (6,1) -- % (6,-2.5) -- (-2,-2.5) -- cycle; % \node[anchor=north west] at (bl) {The \beamerreveal{} package}; % \end{tikzpicture} % \caption{Workflow imposed by the \beamerreveal{} package} % \label{fig:flow} % \end{figure} % % As a nice bonus, the \beamerreveal{} package allows you to generate % \LaTeX{} animations. It's not on the level of Manim \cite{manim}, but for shorter animations % inlined in your deck of slides it is more than functional! % % Finally, you can also include material in iframes. Iframes are HTML % constructs that allow you to incorporate multiple multimedia blocks in HTML. % As an example, this allows incorporating asymptote material that has % been generated for displaying as HTML using webGL. % Note that in many cases, your browser will prohibit these iframes to load external % web content. To solve this, you can run a local webserver and access your presentation % through it. This is explained in Section~\ref{sec:usingscript}. % % \section{Quirks} % Combining \beamer{} and \textsc{reveal} posed one major challenge: % how to make sure that the HTML5 elements appear exactly where you want % them to be, i.e. perfectly aligned with your \LaTeX{} content as it % has been converted to PDF. The core of the problem is twofold: % \begin{itemize} % \item In \beamer{} the aspectratio of the slides is % determined by the class option |aspectratio|. Your PDF viewer uses % letterboxing (black bars on the side) if the aspectratio of your % presentation does not correspond to the aspectratio of your screen. % To the other hand, \textsc{reveal} puts your slides fullscreen % without letterboxing, and therefore the aspectratio is determined by % the screen resolution. % % \item Given the vector-nature of \LaTeX{} and PDF, resolution is not % a parameter you normally care about (everything is vector graphics anyway), % while given the pixel-based nature of traditional multimedia files, % resolution is an issue that you need to think about carefully. % \end{itemize} % % There is only one good solution: ask the users to (1) set the correct % aspectratio using the beamer class options and (2) % specify the width or height of their displaying screen using a % \textsc{beamer-reveal} class option. % % The latter ensures that (a) the background content and the multimedia % files that are generated based on the \LaTeX{} source, are generated % with sufficient resolution, and that (b) the file sizes stay within acceptable limits. % % Actually, there is a one more problem, and that is that the canvas % size and aspectratio of the display area in your browser is % dependent on whether you are viewing full screen or not. % Therefore, an extra requirement arises: (3) when presenting a slide-deck % only you must use your browser in full-screen mode. Otherwise, the alignment is off. % % In order not to have to care about resolutions or the actual % |\pagewidth| or |\pageheight| of your presentation, I've chosen to % impose another constraint: (4) the user must specify locations on % the screen (where to put the multimedia content) as relative % fractions $(x,y)$ where $(0,0)$ corresponds to the bottom left of % the screen and $(1,1)$ corresponds to the top right of the screen. % % \begin{center} % \begin{tikzpicture}[scale=0.3,font=\footnotesize] % \draw[thick] (0,0) rectangle (16,9); % \draw[->] (2,2) node[above right] {coordinate $(0,0)$} -- (0,0); % \draw[->] (14,7) node[below left] {coordinate $(1,1)$} -- (16,9); % \draw[ultra thin] (16.1,9) -- (17,9); % \draw[ultra thin] (16.1,0) -- (17,0); % \draw[<->] (16.8,9) -- node[right] {|\textbackslash{}pageheight|} (16.8,0); % \draw[ultra thin] (0,-0.1) -- (0,-1); % \draw[ultra thin] (16,-0.1) -- (16,-1); % \draw[<->] (0,-0.8) -- node[below] {|\textbackslash{}pagewidth|} (16,-0.8); % \end{tikzpicture} % \end{center} % % However, if you have to specify width and heights of the multimedia % boxes that you want to superimpose on your slides, you don't want to % specify width and height as relative numbers (of the slide width and % height). In that scenario, displaying a 16:9 video on a 16:10 slide % with a width equal to a quarter of the slide width, would require % you to specify: |width=0.25,height=0.225|, which is weird. In % addition, if you'd have to present at a venue where the % projector has a different aspectratio from the one you anticipated, % you would be forced to recalculate all the widths and heights of every % video or image. You % don't want that. Presenting brings sufficient stress without that % extra worry.\\ % Therefore, I imposed a fifth constraint: (5) the user must always specify either width or % height of the box (as a fraction of the respective slide width or % height) together with the aspectratio. Given width and aspectratio % the \textsc{beamer-reveal} package can correctly determine its % relative height; likewise height and aspectratio can be converted % to the correct relative width. Therefore, it is illegal to specify % both width and height at the same time. As the package knows the aspectratio % of the screen (set correctly by the user) no recalculations need to % be done. In the example above, that would mean specifying: % |width=0.25,aspectratio=16/9|, which is very logical. % % When confronted with the situation where you need to present on an old % |4:3| projector, instead of the |16:10| you are used to, this allows you % to just change the beamer aspectratio to |43|, recompile, rerun % |beamer-reveal.pl| and you are good to go on stage. % % So summarized, these are the five rules to go by: % \begin{enumerate} % \item Set the correct aspectratio as a beamer class option. % \item Specify the X or Y-resolution of your displaying screen as a % package option to the \textsc{beamer-reveal} package. % \item Always put your browser in full-screen-mode when presenting. % \item Specify positions relative to the slide width and height, % $(0,0)$ being bottom left and $(1,1)$ being top right. % \item Specify box sizes of the HTML5 content always as the width or % length in combination with the aspectratio. % \end{enumerate} % % % \section{Portability} % These class files should be ready to use with all common modern \LaTeX{} % compilers that produce PDF (XeLaTeX{}, \LuaLaTeX{}, \ldots) % from the major \TeX{}-distributions (TeTeX, TexLive, MikTeX). % If you experience problems with one of these, please inform the author. % % The script |beamer-reveal.pl| is a Perl script, that works on all % major platforms (UNIX, Linux, BSD, Debian, MS-Windows, MAC-OS, % \ldots). % It makes use of the Poppler library and its |pdftoppm| tool, which % is also available for those platforms. % In case you want to use \LaTeX{} animations, it also uses your very own % favorite \LaTeX{}-compiler, |pdfcrop| % (which is part of the major TeX-distributions) and |ffmpeg| a % well-known video conversion tool. % % If these tools are available on your platform, then all should be well. % % \section{Installing the \texttt{beamer-reveal.pl} script} % \subsection{On Linux-like operating systems} % Open a terminal with a shell. Below '|$|' represents your shell prompt. % If needed, update your package list first. Then install the required tools: % \begin{itemize} % \item on a Debian-like OS:\\ % |$ sudo apt install -y perl cpanminus poppler-utils \|\\ % | texlive-extra-utils ffmpeg| % \item on a Redhat-like OS:\\ % |$ sudo dnf install -y epel-release|\\ % |$ sudo dnf install -y https://download1.rpmfusion.org/free/el/rpmfusion-free-release-$(rpm -E %rhel).noarch.rpm|\\ % |$ sudo dnf install -y perl perl-App-cpanminus poppler-utils \|\\ % | texlive-pdfcrop ffmpeg| % \item on openSUSE:\\ % |$ sudo zypper install -y perl perl-App-cpanminus \|\\ % | poppler-tools texlive-pdfcrop ffmpeg| % \item on an Arch-like OS:\\ % |$ sudo pacman -Syu --needed perl cpanminus poppler \|\\ % | texlive-binextra ffmpeg| % \item on Alpine:\\ % |$ sudo apk add perl cpan-app-cpanminus poppler-utils \|\\ % | texlive-extra-utils ffmpeg| % \item on macOS:\\ % |$ brew install perl cpanminus poppler texlive ffmpeg| % \end{itemize} % % \subsection{On MS windows operating systems} % Open a powershell. Below '|$|' represents the powershell prompt. % Install the required tools as follows: % % \begin{minipage}{\textwidth} % |$ winget install StrawberryPerl.StrawberryPerl|\\ % |$ winget install -e --id oschwartz10612.Poppler|\\ % |$ winget install MiKTeX.MiKTeX|\\ % |$ winget install Gyan.FFmpeg|\\ % |$ winget install --id Python.Python.3 --source winget| % \end{minipage} % % You probably need to answer 'Yes' quite some times. If you're asked to restart, % you only need that before moving over to section~\ref{sec:checking} 'Checking your setup'. % You probably already have MiKTeX installed. In that case you can skip % that. However, make sure the 'pdfcrop' program (part of MiKTeX) is installed and available % on your path. % % \subsection{Install \beamerreveal{}} % Open a shell on Linux/macOS, or a powershell prompt on MS-Windows. % Run the following command at the prompt: % % |$ cpanm BeamerReveal| % % This will take a while as this needs to install a number of extra Perl % libraries that have been used in \beamerreveal. You can use the same command to update % the script if a new release has been made. % % The current release number of the Perl package is: |20251230.2042| % % You will see that number appear during the installation. % % \subsection{Checking your setup} % \label{sec:checking} % Open a shell on Linux/macOS, or a command line or powershell prompt on MS-Windows. % Then see whether you can invoke the help information for the tools. % % \begin{minipage}{\textwidth} % |$ cpanm -h|\\ % |$ pdftoppm -h|\\ % |$ pdfcrop --help|\\ % |$ ffmpeg -h|\\ % \end{minipage} % % To test \beamerreveal{} on MS-Windows, run:\\ % |$ beamer-reveal -h| % % On any other platform, run:\\ % |$ beamer-reveal.pl -h| % % If they all display correct help info, you're good to go. % % \section{Using the \texttt{beamer-reveal.pl} script} % \label{sec:usingscript} % If you prepared your \beamer{}-presentation according to Section~\ref{sec:usage}, % then converting it into a reveal.js HTML presentation, is as simple as % running the following command. Make sure the current directory of % the shell is the directory your \LaTeX{}-source file and your % compiled PDF-file is in. % For all commands below, stay in that same working directory! % % \begin{minipage}{\textwidth} % If you document is called |jobname.tex|, then just run:\\ % |$ lualatex jobname.tex|\\ % |$ lualatex jobname.tex| % \end{minipage} % % On MS-Windows, run:\\ % |$ beamer-reveal jobname| % % On any other platform, run:\\ % |$ beamer-reveal.pl jobname| % % Conversion is very fast. Of course, if you need to render some \LaTeX{} % animations, it may take a little more than a jiffy. Especially if % you are working on MS-Windows, because there the generation is fully % single-threaded. % % Next, you can load your document in your browser, e.g.: % % |$ firefox jobname.html| % % If your presentation contains iframe content, you need to start a % local webserver. You don't need a network connection for that. This % is how: % % |$ python -m http.server| % % Then, you can access it through: \url{http://localhost:8000}. % % % \section{Demo} % If you want to see and try out the result of the example that is % embedded in this documentation, check: % \begin{itemize} % \item a 16-by-9 version on: \url{https://www.digmanwaves.net/beamer-reveal/169} % \item a 16-by-10 version on: % \url{https://www.digmanwaves.net/beamer-reveal/1610} % \end{itemize} % % \section{Outreach} % Is there any feature you are missing? Some problems you encounter? % Some inconsistencies in the interface or the documentation? Some % additional features that Reveal supports, but are not in % \beamerreveal? Let me know by dropping me an e-mail. % % If you think \beamerreveal{} makes no sense, let me know why you think % so. I'm keen to learn. % % On the other hand, if you like \beamerreveal{} and are using it, just % send me a kind word. It keeps me going way better than wine or pizza. % % \section{Thanks} % % Thanks to Paul Levrie for proofreading this documentation and testing the package. % % % \newpage % \newgeometry{left=4cm,right=2cm,top=2cm,bottom=2.5cm}% % \section{Usage} % \label{sec:usage} % % \subsection{Package options} % The following package options are available: % \begin{options} % \item[|width|] the width (in pixels) of the screen you will display % the presentation on % \item[|height|] the height (in pixels) of the screen you will % display the presentation on % \end{options} % Only specify one of the two options. The other dimension will be % deduced from the |aspectratio| option that passed onto the beamer % class.\\ % Higher values will give higher resolution of the slides (in the % background), but also larger file sizes. A safety factor is already % used when converting the slides to jpg-format, so taking the true % height or width is recommended. Only when you are bothered with % jpg-artifacts in the final result, you should consider increasing % the width- or height-value. % % \subsection{An enhanced frame environment} % % \DescribeEnv{frame} % The frame environment is defined by \beamer{}. However, it is % equipped with four new environment options by the \beamerreveal{} package: % \begin{options} % \item[|titleslide|] specifies that this slide is a title slide. It % will be on the top level of the reveal menu. This menu can be % invoked by pressing 'm' in your presentation (or clicking on the % pan-cake icon on the bottom left of your presentation). % \item[|sectionslide|] specifies that this slide is a section slide. % It will be on the second level of the reveal menu. % \item[|subsectionslide|] specifies that this slide is a subsection % slide. It will be on the third level of the reveal menu. % \item[|transition|] one of |none|, |zoom|, |fade|, |concave| or % |convex|; these correspond to the available reveal.js transitions. % Not recommended for use. Why? Animation without purpose is bad % practice. % \end{options} % % Slides that are not titleslides, sectionslides or subsectionslides % are ordinary slides. They will appear on the lowest level in the % reveal menu. % % \subsection{The macros to use inside the frame environment} % To understand the operation of the macros, it is important to % realize that the slide content of your beamer-generated PDF will be % put as a background image onto the reveal.js slides. % The extra material such as videos, images and audio will be put as % an overlay on top of that background. The macros allow you to define % what material to put in overlay and where and how big it % should appear. % All macros take options. Some of the options need a value, some not. % Options that take no value are marked with a dagger-symbol in % superscript (\dagger). % % % \DescribeMacro{\video} % This macro will create a video box on the current slide. % Of course a video box can cover the entire slide if desired. % % Its syntax is:\\ % |\video [options] at (x,y) { filename }| % % The arguments are: % \begin{arguments} % \item[|overlay-spec|] a standard beamer overlay specification that % allows you to determine on which overlays the video is to appear; % this argument will end up in a traditional |\only<>{}| clause that % beamer provides. % \item[|options|] the following keys are available. In general they % require a value: |key=value|. % \paragraph{Size options:} % \begin{options} % \item[|width|] the width of the video box (a fraction relative to % the width of the slide) % \item[|height|] the height of the video box (a fraction relative % to the height of the slide) % \item[|aspectratio|] the aspectratio of the video box % \end{options} % Remember that you never specify both |width| and |height|, only one of % those two in combination with the |aspectratio|. % \paragraph{Placement options:} % \begin{options} % \item[|anchor|] value is one of |center|, |north|, |west|, |south|, |east|, % |north east|, |north west|, |south east|, |south west|; this % specifies where the anchor of the video is positioned; the anchor % will be positioned at |(x,y)| % \item[|above|$^\dagger$] synonym to |anchor=south| % \item[|below|$^\dagger$] synonym to |anchor=north| % \item[|left|$^\dagger$] synonym to |anchor=east| % \item[|right|$^\dagger$] synonym to |anchor=west| % \item[|above left|$^\dagger$] synonym to |anchor=south east| % \item[|above right|$^\dagger$] synonym to |anchor=south west| % \item[|below left|$^\dagger$] synonym to |anchor=north east| % \item[|below right|$^\dagger$] synonym to |anchor=north west| % \end{options} % \paragraph{Appearance options:} % \begin{options} % \item[|fit|] the way the video should occupy the box: |fill|, % |cover| or |fit| % \item[|background|] the color of the background of the box % \item[|draw|$^\dagger$] generates an outline around the box that allows you % to inspect where the video will end up in your PDF-file % \item[|autoplay|$^\dagger$] causes the video to start playing a soon as it % appears on the slide % \item[|controls|$^\dagger$] causes player controls to appear below your video % \item[|muted|$^\dagger$] silences the audio of the player % \end{options} % \item[|x|, |y|] the $x$- and $y$-coordinate of the box, specified as a % fraction of the slide width and slide height (dimensionless), fixing % the anchor of the box, w.r.t. the bottom left of your slide. % \item[|filename|] a filename or URL that leads to the video file % (e.g. an mp4 file). Any file playable by your browser will work. % \end{arguments} % % % \DescribeMacro{\audio} % This macro will create an audio block on the current slide. This % block is rather an abstract concept, unless you activate the % controls of the player. Indeed, the audio block will be invisible % unless you specify the option to display the controls of the player. % Its syntax is\\ % |\audio [options] at (x,y) { filename }| % % The arguments are: % \begin{arguments} % \item[|overlay-spec|] a standard beamer overlay specification that % allows you to determine on which overlays the audio is to appear; % this argument will end up in a traditional |\only<>{}| clause that % beamer provides. % \item[|options|] the following keys are available. In general they % require a value: |key=value|. % \paragraph{Size options:} % \begin{options} % \item[|width|] the width of the audio box (a fraction relative to % the width of the slide) % \item[|height|] the height of the audio box (a fraction relative % to the height of the slide) % \item[|aspectratio|] the aspectratio of the audio box % \end{options} % Remember that you never specify both |width| and |height|, only one of % those two in combination with the |aspectratio|. % \paragraph{Placement options:} % \begin{options} % \item[|anchor|] value is one of |center|, |north|, |west|, |south|, |east|, % |north east|, |north west|, |south east|, |south west|; this % specifies where the anchor of the audio box is positioned; the anchor % will be positioned at |(x,y)| % \item[|above|$^\dagger$] synonym to |anchor=south| % \item[|below|$^\dagger$] synonym to |anchor=north| % \item[|left|$^\dagger$] synonym to |anchor=east| % \item[|right|$^\dagger$] synonym to |anchor=west| % \item[|above left|$^\dagger$] synonym to |anchor=south east| % \item[|above right|$^\dagger$] synonym to |anchor=south west| % \item[|below left|$^\dagger$] synonym to |anchor=north east| % \item[|below right|$^\dagger$] synonym to |anchor=north west| % \end{options} % \paragraph{Appearance options:} % \begin{options} % \item[|fit|] the way the audio block should occupy the box: |fill|, % |cover| or |fit| % \item[|background|] the color of the background of the box % \item[|draw|$^\dagger$] generates an outline around the box that allows you % to inspect where the audio box will end up in your PDF-file % \item[|autoplay|$^\dagger$] causes the audio to start playing a soon as it % appears on the slide % \item[|controls|$^\dagger$] causes player controls to appear % \item[|muted|$^\dagger$] silences the audio of the player % \end{options} % \item[|x|, |y|] the $x$- and $y$-coordinate of the box, specified as a % fraction of the slide width and slide height (dimensionless), fixing % the anchor of the box, w.r.t. the bottom left of your slide. % \item[|filename|] a filename or URL that leads to the audio file % (e.g. an mp3 or ogg vorbis file). Any file playable by your browser will work. % \end{arguments} % % \DescribeMacro{\iframe} % This macro will create an iframe box on the current slide. % Of course an iframe box can cover the entire slide if desired. % % Its syntax is:\\ % |\iframe [options] at (x,y) { filename }| % % The arguments are: % \begin{arguments} % \item[|overlay-spec|] a standard beamer overlay specification that % allows you to determine on which overlays the iframe is to appear; % this argument will end up in a traditional |\only<>{}| clause that % beamer provides. % \item[|options|] the following keys are available. In general they % require a value: |key=value|. % \paragraph{Size options:} % \begin{options} % \item[|width|] the width of the iframe box (a fraction relative to % the width of the slide) % \item[|height|] the height of the iframe box (a fraction relative % to the height of the slide) % \item[|aspectratio|] the aspectratio of the iframe box % \end{options} % Remember that you never specify both |width| and |height|, only one of % those two in combination with the |aspectratio|. % \paragraph{Placement options:} % \begin{options} % \item[|anchor|] value is one of |center|, |north|, |west|, |south|, |east|, % |north east|, |north west|, |south east|, |south west|; this % specifies where the anchor of the video is positioned; the anchor % will be positioned at |(x,y)| % \item[|above|] synonym to |anchor=south|;\footnote{\label{novalue}this key allows no value} % \item[|below|] synonym to |anchor=north|;\footnotemark[\value{footnote}] % \item[|left|$^\dagger$] synonym to |anchor=east|;\footnotemark[\value{footnote}] % \item[|right|$^\dagger$] synonym to |anchor=west|;\footnotemark[\value{footnote}] % \item[|above left|$^\dagger$] synonym to |anchor=south east|;\footnotemark[\value{footnote}] % \item[|above right|$^\dagger$] synonym to |anchor=south west|;\footnotemark[\value{footnote}] % \item[|below left|$^\dagger$] synonym to |anchor=north east|;\footnotemark[\value{footnote}] % \item[|below right|$^\dagger$] synonym to |anchor=north west|;\footnotemark[\value{footnote}] % \end{options} % \paragraph{Appearance options:} % \begin{options} % \item[|fit|] the way the iframe should occupy the box: |fill|, % |cover| or |fit| % \item[|background|] the color of the background of the box % \item[|draw|] generates an outline around the box that allows you % to inspect where the iframe will end up in your PDF-file;\footnotemark[\value{footnote}] % \end{options} % \item[|x|, |y|] the $x$- and $y$-coordinate of the box, specified as a % fraction of the slide width and slide height (dimensionless), fixing % the anchor of the box, w.r.t. the bottom left of your slide. % \item[|filename|] a filename or URL that leads to the iframe content % (e.g. an HTML file generated by asymptote). Note that for the content to work, % you might need to serve your presentation through a local html server:\\ % |$ python -m http.server| % \end{arguments} % % \DescribeMacro{\image} % This macro will create an image box on the current slide. % Of course an image box can cover the entire slide if desired. % % Note that using the |\includegraphics| command of the |graphicx| % package is still preferred to include the standard image formats, % such as PDF, PNG, TIFF and JPG. However, the |image| command also % allows to include (animated) GIFs and SVG files. % % Its syntax is:\\ % |\image[options] at (x,y) { filename }| % % The arguments are: % \begin{arguments} % \item[|overlay-spec|] a standard beamer overlay specification that % allows you to determine on which overlays the image is to appear; % this argument will end up in a traditional |\only<>{}| clause that % beamer provides. % \item[|options|] the following keys are available. In general they % require a value: |key=value|. % \paragraph{Size options:} % \begin{options} % \item[|width|] the width of the image box (a fraction relative to % the width of the slide) % \item[|height|] the height of the image box (a fraction relative % to the height of the slide) % \item[|aspectratio|] the aspectratio of the image box % \end{options} % Remember that you never specify both |width| and |height|, only one of % those two in combination with the |aspectratio|. % \paragraph{Placement options:} % \begin{options} % \item[|anchor|] value is one of |center|, |north|, |west|, |south|, |east|, % |north east|, |north west|, |south east|, |south west|; this % specifies where the anchor of the image is positioned; the anchor % will be positioned at |(x,y)| % \item[|above|$^\dagger$] synonym to |anchor=south|;\footnote{\label{novalue}this key allows no value} % \item[|below|$^\dagger$] synonym to |anchor=north|;\footnotemark[\value{footnote}] % \item[|left|$^\dagger$] synonym to |anchor=east|;\footnotemark[\value{footnote}] % \item[|right|$^\dagger$] synonym to |anchor=west|;\footnotemark[\value{footnote}] % \item[|above left|$^\dagger$] synonym to |anchor=south east|;\footnotemark[\value{footnote}] % \item[|above right|$^\dagger$] synonym to |anchor=south west|;\footnotemark[\value{footnote}] % \item[|below left|$^\dagger$] synonym to |anchor=north east|;\footnotemark[\value{footnote}] % \item[|below right|$^\dagger$] synonym to |anchor=north west|;\footnotemark[\value{footnote}] % \end{options} % \paragraph{Appearance options:} % \begin{options} % \item[|fit|] the way the image should occupy the box: |fill|, % |cover| or |fit| % \item[|background|] the color of the background of the box % \item[|draw|] generates an outline around the box that allows you % to inspect where the image will end up in your PDF-file;\footnotemark[\value{footnote}] % \end{options} % \item[|x|, |y|] the $x$- and $y$-coordinate of the box, specified as a % fraction of the slide width and slide height (dimensionless), fixing % the anchor of the box, w.r.t. the bottom left of your slide. % \item[|filename|] a filename or URL of the image file % (e.g. a GIF file). % \end{arguments} % % \DescribeMacro{\animation} % This macro will create an animation box on the current slide. % Different from the other boxes, this box will determine its own width and % height, based on the dimensions of the LaTeX content embedded in it. % In fact, it is illegal to specify aspectratio, width or height. % % The animation is generated as follows: the content of macro will be % written by the |beamer-reveal.pl| script % to a separate LaTeX file using the |standalone| class. % The preamble that it uses will be the part of the preamble in your % beamer source file, in between the loading of the |beamer-reveal| package % and the line containing |\begin{document}|. The animation block will be % embedded in a loop that will be executed |duration| $\cdot$ % |framerate| times, providing a macro |\progress| that contains a % fraction that goes up from $0$ (first iteration) to $1$ last % iteration. The PDF-file that is generated with this standalone file, % is converted to an mp4-file that is included as a video on your % slide.\\ % The tools used for this are the \LaTeX{}-compiler you used for your beamer sourcefile, % |pdfcrop| \cite{pdfcrop}, |pdftoppm| \cite{pdftoppm} and |ffmpeg| \cite{ffmpeg}. % % This animation generation takes advantage of the multicore nature of % your computer, by simple, but smart parallelization (on % non-MS-Windows operating systems). % % Its syntax is:\\ % |\animation [options] at (x,y) { animation-LaTeX-content }| % % The arguments are: % \begin{arguments} % \item[|overlay-spec|] a standard beamer overlay specification that % allows you to determine on which overlays the animation is to appear; % this argument will end up in a traditional |\only<>{}| clause that % beamer provides. % \item[|options|] the following keys are available. In general they % require a value: |key=value|. % \paragraph{Size options:} no size options; size is determined from % the \LaTeX{} code itself! % % \paragraph{Generation options:} % \begin{options} % \item[|framerate|] number of frames per second that the animation % should contain. % \item[|duration|] duration (in seconds) of the animation % \item[|pdfprogress|] value that the progress macro will take on when % a picture of the animation frame is made in your PDF-file. % \end{options} % The number of frames that will be generated for the animation is: % \begin{align} % \texttt{number-of-frames} = \texttt{framerate} \cdot \texttt{duration} % \end{align} % Your PDF file will contain a single shot of the animation (as if it % were a preview shot). For this frame, the value of the |\progress| % macro will be set to |pdfprogress|. % % \paragraph{Placement options:} % \begin{options} % \item[|anchor|] value is one of |center|, |north|, |west|, |south|, |east|, % |north east|, |north west|, |south east|, |south west|; this % specifies where the anchor of the animation is positioned; the anchor % will be positioned at |(x,y)| % \item[|above|$^\dagger$] synonym to |anchor=south| % \item[|below|$^\dagger$] synonym to |anchor=north| % \item[|left|$^\dagger$] synonym to |anchor=east| % \item[|right|$^\dagger$] synonym to |anchor=west| % \item[|above left|$^\dagger$] synonym to |anchor=south east| % \item[|above right|$^\dagger$] synonym to |anchor=south west| % \item[|below left|$^\dagger$] synonym to |anchor=north east| % \item[|below right|$^\dagger$] synonym to |anchor=north west| % \end{options} % \paragraph{Appearance options:} % \begin{options} % \item[|background|] the color of the background of the box % \item[|draw|$^\dagger$] generates an outline around the box that allows you % to inspect where the video will end up in your PDF-file % \item[|autoplay|$^\dagger$] causes the video to start playing a soon as it % appears on the slide % \item[|controls|$^\dagger$] causes player controls to appear below your video % \item[|muted|$^\dagger$] silences the audio of the player % \end{options} % % \item[|x|, |y|] the $x$- and $y$-coordinate of the box, specified as a % fraction of the slide width and slide height (dimensionless), fixing % the anchor of the box, w.r.t. the bottom left of your slide. % \item[|animation-LaTeX-content|] the LaTeX code that generates every % frame based on the |\progress| 'time variable'. % \end{arguments} % \clearpage % % \newgeometry{left=1.75cm,right=1.75cm,top=2cm,bottom=2.5cm} % % \section{Example} % % \subsection{Using the example} % An example will allow you to get an idea of the convenience of the package. % The following steps will allow you to observe it in your browser: % % |$ lualatex beamer-reveal-example.tex|\\ % |$ beamer-reveal.pl beamer-reveal-example|\\ % |$ python -m http.server| % % Then open in your browser: \url{localhost:8000} and enjoy! % % \subsection{The source code of the example} % \begin{verbatim} %<*example> \documentclass[11pt,aspectratio=169,t]{beamer} \setbeamertemplate{navigation symbols}{} \usepackage[width=1920]{beamer-reveal} \usepackage{tikz} \usepackage{siunitx} \newcommand\eu{\mathrm{e}} \newcommand\ju{\mathrm{j}} \title{Test slide deck} \subtitle{\textsc{beamer-reveal}} \author{Walter Daems} \begin{document} \begin{frame}[titleslide] \titlepage \end{frame} \AtBeginSection{ \begin{frame}[sectionslide]{Overview} \tableofcontents[currentsection] \end{frame} } \AtBeginSubsection{ \begin{frame}[subsectionslide]{Overview} \tableofcontents[currentsection,currentsubsection] \end{frame} } \section{Introduction} \subsection{Slide making} \begin{frame} {Good news} {} You can keep on making your slides the way you are used to! \begin{itemize} \item all the nice \LaTeX{} stuff at your fingertips \item no tempation to use too much unnecessary animation \end{itemize} \bigskip Indeed, there are no tools that can typeset equations like the tools form the \TeX-ecosystem: \begin{equation} \eu^{-\ju\pi}+1=0 \end{equation} \end{frame} \begin{frame}[transition=concave] {A dummy slide} {number one} \vfill Showing off the 'concave' slide transition animation. Not recommended! \vfill \end{frame} \begin{frame}[transition=convex] {A dummy slide} {number two} \vfill Showing off the 'convex' slide transition animation. Not recommended! \vfill \end{frame} \subsection{Pimping your slides} \begin{frame} {And even more good news} {\ldots almost seems to good to be true\ldots} \small However, now you can pimp your slides like never before. You can incorporate: \begin{itemize} \item videos and audio fragments \item animated GIFs and LaTeX animations \item iframe content \end{itemize} without being tied to Acrobat reader. In addition, there are some extra features \begin{itemize} \item press '?' for keyboard help, amongst which you will find: \item press 'm' to open the slide menu on the left \item press 'o' to get an overview of the slides \item press 's' to start a speaker view \item press 'g' to go to a specific slide by typing its slide number \end{itemize} The pancake menu on the bottom left also opens the menu. \end{frame} \begin{frame}[transition=zoom] {A dymmy slide} {number three} \vfill Showing off the 'zoom slide transition animation. Not recommended! \vfill \end{frame} \section{In detail} \subsection{Candy for the eye} \begin{frame} {Placing videos} {} \only<1>{On this first slide there is nothing to see. On the next animation frame, a video will appear.} \only<2>{Here it is!} \video<2>[above,draw,autoplay,height=0.7,aspectratio=16/9, background=yellow,fit=contain] at (0.5,0.1) {Media/beamer-reveal-testvideo.mp4} \end{frame} \begin{frame} {Placing images (possibly animated)} {} \begin{columns} \column[T]{0.45\textwidth} Below you will find a png (for which you don't need reveal, BTW). \vspace*{1cm} But you can exploit the transparency! \vspace*{2.5cm} And on the top right you will find a swinging pendulum (an animated GIF). \column[T]{0.45\textwidth} \end{columns} \image[width=0.33,aspectratio=1,fit=contain] at (0.7,0.6) {Media/beamer-reveal-AnimatedPendulum.gif} \image[width=0.25,aspectratio=1,fit=contain] at (0.2,0.6) {Media/beamer-reveal-WiresTp.png} \end{frame} \begin{frame} {Placing iframe material (possibly animated)} {e.g. generated with asymptote} Click and drag on the iframe below. You can manipulate it! Use your mouse scroll-wheel to zoom in or out. \iframe[draw,anchor=north,height=0.6,aspectratio=16/9, fit=cover] at (0.5,0.7) {Media/beamer-reveal-PCB.html} \end{frame} \subsection{Resonance for the ear} \begin{frame} {Adding audio to your slides} {} On the very bottom right, there is an audio block that automatically starts playing. \audio[draw,autoplay,controls,width=0.1,aspectratio=16/9, background=blue,fit=cover] at (0.85,0.1) {Media/beamer-reveal-AudioSample.ogg} \end{frame} \subsection{Make (video) animations with LaTeX} \begin{frame}[fragile] {Making animations with LaTeX (using TikZ as example)} {It is easier than ever before} \small The animation content is exported to a standalone \LaTeX-document that creates a loop over it, for a duration of \texttt{duration} seconds at \texttt{framerate} frames per second providing a \texttt{\textbackslash{}progress} variable that goes gradually from 0 to 1 in \texttt{duration} $\times$ \texttt{framerate} frames. The beamer-reveal.pl script transforms it to mp4 exploiting your full potential of your multi-core hardware. \animation[framerate=25,duration=7.5,pdfprogress=0.1,autoplay,loop] at (0.5,0.35) { \begin{tikzpicture}[font=\footnotesize,transform shape,scale=0.75] \pgfmathsetmacro\angle{\progress*540}% \clip (-2,-5.25) rectangle (8,2); \node[below left,inner sep=1pt] at (0,0) {\tiny 0}; \node[below left,inner sep=1pt] at (2.5,0) {\tiny 0}; \node[above right,inner sep=1pt] at (0,-2) {\tiny 0}; \begin{scope}[every node/.style={right}] \node[thick,draw,rectangle] at (2.5,-2) {\large $x(t) = A \cdot \eu^{j\omega t}$}; \node at (3.5,-3) {\large $\eu^{j\alpha} = \cos\alpha+j\sin\alpha$}; \node at (2.5,-4) {\large $x(t) = \underbrace{A \cos \omega t}_{\text{\textcolor{orange}{real}}} + \underbrace{j A \sin \omega t}_{\text{\textcolor{olive}{imaginary}}}$}; \end{scope} \draw[->,thick] (3,-2.4) -- (3,-3.4); \draw[blue,thick] (0,0) circle (1); \draw[->] (-1.25,0) -- (1.25,0) node[below] {Re}; \draw[->] (0,-1.25) -- (0,1.25) node[left] {Im}; % circle \draw[olive,very thick] (0,0) -- (0,{sin(\angle)}); \draw[orange,very thick] (0,0) -- ({cos(\angle)},0); \draw[blue,thick,->] (0,0) -- node[left,font=\tiny] {A} +(\angle:1); \draw[->] (0.4,0) arc (0:\angle:0.4); \node at (0.5*\angle:0.7) {\scriptsize $\omega \tilde t$}; % right graph \draw[very thick,olive] ({2.5+\angle/180},0) -- +(0,{sin(\angle)}); \draw[densely dotted] ({min(0,cos(\angle))},{sin(\angle)}) -- ({2.5+\angle/180},{sin(\angle)}); \draw[thick] ({2.5+\angle/180},0) +(0,1pt) -- +(0,-1pt) node[below] {$\tilde t$}; % bottom graph \draw[very thick,orange] (0,{-2-\angle/180}) -- +({cos(\angle)},0); \draw[densely dotted] ({cos(\angle)},{max(0,sin(\angle))}) -- ({cos(\angle)},{-2-\angle/180}); \draw[thick] (0,{-2-\angle/180}) +(1pt,0) -- +(-1pt,0) node[left] {$\tilde t$}; % right graph \foreach \y/\l in {-1/-A,1/A} { \draw[gray,densely dotted] (2.5,\y) -- (6.25,\y); \draw (2.5,\y) +(+1pt,0) -- +(-1pt,0) node[left] {$\l$}; } \draw[->] (2.0,0) -- (6.5,0) node[below] {$t$}; \draw[->] (2.5,-1.25) -- (2.5,1.25) node[left] {$Im(x(t))$}; \draw[olive,thick,domain=-0.25:3.5,samples=30,smooth] plot ({\x+2.5},{sin(pi*\x r)}); % bottom graph \foreach \y/\l in {-1/-A,1/A} { \draw[gray,densely dotted] (\y,-2) -- (\y,-4.5); \draw (2.5,\y) +(+1pt,0) -- +(-1pt,0) node[left] {$\l$}; } \draw[->] (-1.25,-2) -- (1.25,-2) node[above] {$Re(x(t))$}; \draw[->] (0,-1.5) -- (0,-5) node[left] {$t$}; \draw[orange,thick,domain=-0.25:2.6,samples=30,smooth] plot ({cos(pi*\x r)},{-2-\x}); \end{tikzpicture} } \end{frame} \end{document} % % \end{verbatim} % \clearpage % % \StopEventually{\clearpage\PrintChanges\PrintIndex} % % \section{Implementation} % % \subsection{The preamble of the package} % % \begin{macrocode} %<*reveal> \ExplSyntaxOn \RequirePackage{l3keys2e} % % \end{macrocode} % % \subsection{Error/warning messages} % % \begin{macrocode} %<*reveal> \msg_new:nnn{ beamer-reveal } { inconsistent-dimensions } { aspect~ratio~of~beamer~(#1)~and~reveal~(#2:#3)~are~not~consistent.\\ You~must~specify~consistent~values~for~width/height~and~aspectratio~ otherwise~your~reveal~items~(videos/images/animations)~will~not~appear~ on~the~right~locations~on~your~reveal-slidedeck. } \msg_new:nnn{ beamer-reveal } { missing-aspectratio } { missing~aspect~ratio.\\ You~need~to~specify~at~least~an~aspect~ratio~for~a~beamer-reveal~item~ you~want~to~put~on~the~reveal~slide. } \msg_new:nnn{ beamer-reveal } { missing-width-or-height } { missing~width~or~height.\\ You~need~to~specify~at~least~a~width~or~a~height~for~a~beamer-reveal~item~ you~want~to~put~on~the~reveal~slide. } \msg_new:nnn{ beamer-reveal } { overconstrained-box } { overconstrained~box.\\ You~cannot~both~specify~the~width~and~the~height~of~a~beamer-reveal~item~ you~want~to~put~on~the~slide. Specify~width~and~aspectratio~or~height~and~aspectratio. } \msg_new:nnn{ beamer-reveal } { dynamic-option-for-staticcontent } { dynamic~option~given~(autoplay,~controls,~loop,~muted)~for~static~ content~(\image,~\iframe).\\ These~options~make~no~sense~for~the~\image~command.~Remove~them. } \msg_new:nnn{ beamer-reveal } { animation-option-for-nonanimation } { duration~and~framerate~are~options~that~can~only~be~given~for~the~ \animation~command.\\ Remove~them~from~the~\video,~\audio,~\image~and~\iframe~commands. } % % \end{macrocode} % % % % % \subsection{Package options} % First some global variables to store the global width and height of % the presentation, that can be specified as package options: % \begin{macrocode} %<*reveal> \tl_new:N \g_@@_beameraspectratio_tl \tl_set:Nn \g_@@_beameraspectratio_tl {43} \fp_new:N \g_@@_canvaswidth_fp \fp_set:Nn \g_@@_canvaswidth_fp { \dim_to_fp:n {\paperwidth} } \fp_new:N \g_@@_canvasheight_fp \fp_set:Nn \g_@@_canvasheight_fp { \dim_to_fp:n {\paperheight} } \fp_new:N \g_@@_canvasaspectratio_fp \fp_set:Nn \g_@@_canvasaspectratio_fp { \g_@@_canvaswidth_fp / \g_@@_canvasheight_fp } \int_new:N \g_@@_canvaswidth_int \int_set:Nn \g_@@_canvaswidth_int {0} \int_new:N \g_@@_canvasheight_int \int_set:Nn \g_@@_canvasheight_int {0} \keys_define:nn { beamerreveal } { width .int_set:N = \g_@@_canvaswidth_int, width .value_required:n = true, height .int_set:N = \g_@@_canvasheight_int, height .value_required:n = true, } \ProcessKeyOptions[beamerreveal] \message{ PW~: \fp_use:N \g_@@_canvaswidth_fp } \message{ PH~: \fp_use:N \g_@@_canvasheight_fp } \int_compare:nNnTF { \g_@@_canvaswidth_int } = {0} { \int_compare:nNnTF { \g_@@_canvasheight_int } = {0} { % we assume 4x3 on an HD screen \int_set:Nn \g_@@_canvaswidth_int { 1920 } \int_set:Nn \g_@@_canvasheight_int { \fp_eval:n { round( \g_@@_canvaswidth_int / \g_@@_canvasaspectratio_fp ) } } } { % we assume 4x3 \int_set:Nn \g_@@_canvaswidth_int { \fp_eval:n { round( \g_@@_canvasheight_int * \g_@@_canvasaspectratio_fp ) } } } } { \int_compare:nNnTF { \g_@@_canvasheight_int } = {0} { % we assume 4x3 on an HD screen \int_set:Nn \g_@@_canvasheight_int{ \fp_eval:n { round( \g_@@_canvaswidth_int / \g_@@_canvasaspectratio_fp ) } } } { % both are set, we're good to go \fp_new:N \l_@@_canvasaspectratioresidue_fp \fp_set:Nn \l_@@_canvasaspectratioresidue_fp { \fp_abs:n { \g_@@_canvaswidth_int / \g_@@_canvasheight_int - \g_@@_canvasaspectratio_fp } } \fp_compare:nNnTF { \l_@@_canvasaspectratioresidue_fp } > {0.001} { \msg_warning:nneee { beamer-reveal } { inconsistent-dimensions } { \tl_use:N \g_@@_beameraspectratio_tl } { \int_use:N \g_@@_canvaswidth_int } { \int_use:N \g_@@_canvasheight_int } }{} } } % % \end{macrocode} % \subsection{Extra options for the frame environment of \beamer{}} % % \begin{macrocode} %<*reveal> \bool_new:N \g_@@_titlepage_bool \define@key{beamerframe}{titleslide}[true]{% \ExplSyntaxOn \bool_gset_true:N \g_@@_titlepage_bool \ExplSyntaxOff } \bool_new:N \g_@@_sectionslide_bool \define@key{beamerframe}{sectionslide}[true]{% \ExplSyntaxOn \bool_gset_true:N \g_@@_sectionslide_bool \ExplSyntaxOff } \bool_new:N \g_@@_subsectionslide_bool \define@key{beamerframe}{subsectionslide}[true]{% \ExplSyntaxOn \bool_gset_true:N \g_@@_subsectionslide_bool \ExplSyntaxOff } \tl_new:N \g_@@_transition_tl \define@key{beamerframe}{transition}[none]{% \ExplSyntaxOn \tl_gset:Nn \g_@@_transition_tl { #1 } \ExplSyntaxOff } % % \end{macrocode} % % \subsection{File writing} % File handles and auxiliary functions to write data to the |.rvl| % file. % % \begin{macrocode} %<*reveal> \iow_new:N \g_@@_rvlfile \iow_open:Nn \g_@@_rvlfile {\jobname.rvl} % % \end{macrocode} % % \begin{macro}{\writecomment\_@@:n} % \begin{macrocode} %<*reveal> \cs_new:Npn \writecomment_@@:n #1 { \iow_now:Ne \g_@@_rvlfile {\c_percent_str\c_percent_str\c_space_tl #1} } % % \end{macrocode} % \end{macro} % % \begin{macro}{\writecontrol\_@@:n} % \begin{macrocode} %<*reveal> \cs_new:Npn \writecontrol_@@:nn #1 #2 { \iow_now:Ne \g_@@_rvlfile {@ @#1:~#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{\writeliteral\_@@:n} % \begin{macrocode} \cs_new:Npn \writeliteral_@@:n #1 { \iow_now:Nx \g_@@_rvlfile {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}{\writeraw\_@@:n} % \begin{macrocode} \cs_new:Npn \writeraw_@@:n #1 { \iow_now:Nn \g_@@_rvlfile { #1 } } % \end{macrocode} % \end{macro} % Now initialize our \texttt{.rvl} file. % % \begin{macrocode} \writecomment_@@:n {Beamer-reveal driver file} \writecontrol_@@:nn {Presentation} {} \tl_new:N \l_@@_my_compiler_tl \tl_set:Nn \l_@@_my_compiler_tl { unknown } \sys_if_engine_pdftex:T { \tl_set:Nn \l_@@_my_compiler_tl { pdflatex } } \sys_if_engine_xetex:T { \tl_set:Nn \l_@@_my_compiler_tl { xelatex } } \sys_if_engine_luatex:T { \tl_set:Nn \l_@@_my_compiler_tl { lualatex } } \writeliteral_@@:n {-parameters: compiler={\tl_use:N \l_@@_my_compiler_tl }, canvaswidth={\int_use:N \g_@@_canvaswidth_int}, canvasheight={\int_use:N \g_@@_canvasheight_int} } % % \end{macrocode} % % \subsection{Frame generation} % % \begin{macrocode} %<*reveal> \AddToHook{ env / frame / begin} { \bool_gset_false:N \g_@@_titlepage_bool \bool_gset_false:N \g_@@_sectionslide_bool \bool_gset_false:N \g_@@_subsectionslide_bool \tl_gset:Nn \g_@@_transition_tl {none} } \AddToHook{ env / beamer@frameslide / before} { \writecontrol_@@:nn {BeamerFrame} {} } \AddToHook{ env / beamer@frameslide / after} { \writeliteral_@@:n {-parameters:rawpage={\insertpagenumber}, truepage={\insertframenumber}, overlay={\insertoverlaynumber}, transition={\tl_use:N \g_@@_transition_tl}, \bool_if:NTF \g_@@_sectionslide_bool { title={\secname},toc={section} } { \bool_if:NTF \g_@@_subsectionslide_bool { title={\subsecname},toc={subsection} } { \bool_if:NTF \g_@@_titlepage_bool { title={\inserttitle},toc={titlepage} } { title={\beamer@frametitle} } } } } } % % \end{macrocode} % % \subsection{Common keys for the macros} % % \begin{macrocode} %<*reveal> \fp_new:N \l_@@_mediawidth_fp \fp_new:N \l_@@_mediaheight_fp \fp_new:N \l_@@_mediaframerate_fp \fp_new:N \l_@@_mediaduration_fp \fp_new:N \l_@@_mediapdfprogress_fp \tl_new:N \l_@@_mediafit_tl \tl_new:N \l_@@_mediabackground_tl \fp_new:N \l_@@_xposdelta_fp \fp_new:N \l_@@_yposdelta_fp \bool_new:N \_@@_mediaautoplay_bool \bool_new:N \_@@_medialoop_bool \bool_new:N \_@@_mediaboxdraw_bool \bool_new:N \_@@_mediamuted_bool \bool_new:N \_@@_mediacontrols_bool \tl_new:N \l_@@_mediaanchor_tl \msg_new:nnn { beamerreveal / media } { unknown-key } { Unknown~key~'#1'~for~media~(video,~animated,~...)~command. } \msg_new:nnn { beamerreveal / media } { illegal-keys-video } { Illegal~key(s)~'#1'~for~a~\video. } \msg_new:nnn { beamerreveal / media } { illegal-keys-image } { Illegal~key(s)~'#1'~for~an~\image. } \msg_new:nnn { beamerreveal / media } { illegal-keys-iframe } { Illegal~key(s)~'#1'~for~an~\iframe. } \msg_new:nnn { beamerreveal / media } { illegal-keys-animation } { Illegal~key(s)~'#1'~for~an~\animation. } \keys_define:nn { beamerreveal / media } { width .fp_set:N = \l_@@_mediawidth_fp, width .value_required:n = true, width .initial:n = 0, width .groups:n = { size }, height .fp_set:N = \l_@@_mediaheight_fp, height .value_required:n = true, height .initial:n = 0, height .groups:n = { size }, aspectratio .fp_set:N = \l_@@_mediaaspectratio_fp, aspectratio .value_required:n = true, aspectratio .groups:n = { size }, fit .tl_set:N = \l_@@_mediafit_tl, fit .value_required:n = true, fit .initial:n = fill, fit .groups:n = { fit }, background .tl_set:N = \l_@@_mediabackground_tl, background .value_required:n = true, background .initial:n = white, background .groups:n = { draw }, draw .bool_set:N = \l_@@_mediaboxdraw_bool, draw .groups:n = { draw }, autoplay .bool_set:N = \l_@@_mediaautoplay_bool, autoplay .initial:n = false, autoplay .groups:n = { dynamic }, loop .bool_set:N = \l_@@_medialoop_bool, loop .initial:n = false, loop .groups:n = { dynamic }, controls .bool_set:N = \l_@@_mediacontrols_bool, controls .initial:n = false, controls .groups:n = { dynamic }, muted .bool_set:N = \l_@@_mediamuted_bool, muted .initial:n = false, muted .groups:n = { dynamic }, duration .fp_set:N = \l_@@_mediaduration_fp, duration .initial:n = 0, duration .value_required:n = true, duration .groups:n = { animation }, pdfprogress .fp_set:N = \l_@@_mediapdfprogress_fp, pdfprogress .initial:n = 0, pdfprogress .value_required:n = true, pdfprogress .groups:n = { animation }, framerate .fp_set:N = \l_@@_mediaframerate_fp, framerate .initial:n = 0, framerate .value_required:n = true, framerate .groups:n = { animation }, anchor .choice:, anchor / center .code:n = { \fp_set:Nn \l_@@_xposdelta_fp { -0.5 } \fp_set:Nn \l_@@_yposdelta_fp { -0.5 } \tl_set:Nn \l_@@_mediaanchor_tl {#1} }, anchor / west .code:n = { \fp_set:Nn \l_@@_xposdelta_fp { 0 } \fp_set:Nn \l_@@_yposdelta_fp { -0.5 } \tl_set:Nn \l_@@_mediaanchor_tl {#1} }, anchor / north~west .code:n = { \fp_set:Nn \l_@@_xposdelta_fp { 0 } \fp_set:Nn \l_@@_yposdelta_fp { 0 } \tl_set:Nn \l_@@_mediaanchor_tl {#1} }, anchor / north .code:n = { \fp_set:Nn \l_@@_xposdelta_fp { -0.5 } \fp_set:Nn \l_@@_yposdelta_fp { 0 } \tl_set:Nn \l_@@_mediaanchor_tl {#1} }, anchor / north~east .code:n = { \fp_set:Nn \l_@@_xposdelta_fp { -1 } \fp_set:Nn \l_@@_yposdelta_fp { 0 } \tl_set:Nn \l_@@_mediaanchor_tl {#1} }, anchor / east .code:n = { \fp_set:Nn \l_@@_xposdelta_fp { -1 } \fp_set:Nn \l_@@_yposdelta_fp { -0.5 } \tl_set:Nn \l_@@_mediaanchor_tl {#1} }, anchor / south~east .code:n = { \fp_set:Nn \l_@@_xposdelta_fp { -1 } \fp_set:Nn \l_@@_yposdelta_fp { -1 } \tl_set:Nn \l_@@_mediaanchor_tl {#1} }, anchor / south .code:n = { \fp_set:Nn \l_@@_xposdelta_fp { -0.5 } \fp_set:Nn \l_@@_yposdelta_fp { -1 } \tl_set:Nn \l_@@_mediaanchor_tl {#1} }, anchor / south~west .code:n = { \fp_set:Nn \l_@@_xposdelta_fp { 0 } \fp_set:Nn \l_@@_yposdelta_fp { -1 } \tl_set:Nn \l_@@_mediaanchor_tl {#1} }, anchor .value_required:n = true, anchor .initial:n = center, anchor .groups:n = { position }, above .meta:n = { anchor = south }, above .groups:n = { position }, below .code:n = { anchor = north }, below .groups:n = { position }, left .code:n = { anchor = east }, left .groups:n = { position }, right .code:n = { anchor = west }, right .groups:n = { position }, above~left .code:n = { anchor = south east }, above~left .groups:n = { position }, above~right .code:n = { anchor = south west }, above~right .groups:n = { position }, below~left .code:n = { anchor = north east }, below~left .groups:n = { position }, below~right .code:n = { anchor = north west }, below~right .groups:n = { position }, unknown .code:n = { \msg_error:nne { beamerreveal / media } { unknown-key } {\l_keys_key_str} }, } % % \end{macrocode} % % \subsection{Fiddling with relative widths/heights} % As mentioned in the section 'quirks' the package only allows specifying % box dimensions as height and an apsect ratio, or width and an % aspectratio. \textsc{beamer-reveal} will recalculate these into % fractional values relative to the slide width and height.\\ % In order not to get lost in the calculations, let's find the equations we need to implement. % Let's call the absolute width and height $W$ and $L$ and the relative width and height $w$ and $h$. % Let $P_W$ and $P_H$ be the absolute page width and height. Obviously: % \begin{align} % w &= \frac{W}{W_P} & h = \frac{H}{H_P} % \end{align} % Now let's denote the aspectratio of an object as $A$ and the aspectratio of the page as $A_P$. % \begin{align} % A &= \frac{W}{H} & A_P &=\frac{W_P}{H_P} % \end{align} % This allows to calculate $w$ from $h$ and vice versa: % \begin{align} % w &= \frac{W}{W_P} = \frac{AH}{A_P H_P} = \frac{A}{A_P} h & % h &= \frac{H}{H_P} = \frac{W/A}{W_P/A_P} = \frac{A_P}{A} w % \end{align} % The following macro calculates verifies if at least the aspectratio $A$ has been given otherwise % a fatal error is generated. It then calculates $w$ from $h$ or $h$ from $w$ unless both $w$ and $h$ % are missing, or unless both have been specified. % \begin{macro}{\process\_a\_w\_h\_@@:NNN} % \begin{macrocode} %<*reveal> \cs_new:Npn \process_a_w_h_@@:NNN #1#2#3 { \fp_compare:nNnTF { #1 } = {0} { \msg_fatal:nn { beamer-reveal } { missing-aspectratio } } { \fp_compare:nNnTF { #2 } = {0} { \fp_compare:nNnTF { #3 } = {0} { \msg_fatal:nn { beamer-reveal } { missing-width-or-height } } { % calculating w \fp_gset:Nn \l_tmpa_fp { round( #1 / \g_@@_canvasaspectratio_fp * #3, 6 ) } \fp_gset:Nn \l_tmpb_fp { #3 } } } { \fp_compare:nNnTF { #3 } = {0} { } { \msg_fatal:nn { beamer-reveal } { overconstrained-box } } { % calculating h \fp_gset:Nn \l_tmpa_fp { #2 } \fp_gset:Nn \l_tmpb_fp { round( \g_@@_canvasaspectratio_fp / #1 * #2, 6 ) } } } } \fp_set_eq:NN #2 \l_tmpa_fp \fp_set_eq:NN #3 \l_tmpb_fp } % % \end{macrocode} % \end{macro} % % \subsection{Auxiliary functions} % % \begin{macro}{\extractloleft} % \begin{macrocode} %<*reveal> \newdimen\xloleft \newdimen\yloleft \newcommand*\extractloleft[1]{\path (#1);\pgfgetlastxy{\xloleft}{\yloleft};} % % \end{macrocode} % \end{macro} % % \begin{macro}{\extractupright} % \begin{macrocode} %<*reveal> \newdimen\xupright \newdimen\yupright \newcommand*\extractupright[1]{\path (#1);\pgfgetlastxy{\xupright}{\yupright};} % % \end{macrocode} % \end{macro} % % Finally, some native l3exp fp variables to hold $x$ and $y$ position. % % \begin{macrocode} %<*reveal> \fp_new:N \l_@@_xpos_fp \fp_new:N \l_@@_ypos_fp % % \end{macrocode} % % \subsection{Macros} % \subsubsection{Main macros} % The macro's fiddle with positions and sizes of boxes. Therefore it helps to have the following % pictures in mind when reading the code. % % The parameters |\posx| and |\posy| are the relative \textsc{beamer} coördinates of the box. % The parameters |\l_@@_xpos_fp| and |\l_@@_ypos_fp| are the HTML top and left distances % of the top left corner of the box. All parameters are relative to the screen canvas dimensions % (and therefore have values in between 0 and 1). % % \begin{center} % \begin{tikzpicture}[scale=0.4,font=\footnotesize, % inner sep=1pt] % \draw[thick] (0,0) node[below right] {Screen canvas} rectangle (18,10); % \coordinate (m) at (12,5); % \coordinate (c) at ($(m)+(-3,2)$); % \draw[semithick] ($(m)-(3,2)$) node[below right] {Box} rectangle ($(m)+(3,2)$); % \fill (m) circle[radius=2pt]; % \draw[<->] (m|-0,0) -- node[right,pos=0.33] {|\textbackslash{}posy|} (m); % \draw[<->] (m-|0,0) -- node[below,pos=0.4] {|\textbackslash{}posx|} (m); % \draw[<->] (c|-0,10) -- node[right,pos=0.5] {|\textbackslash{}l\_@@\_ypos\_fp|} (c); % \draw[<->] (c-|0,10) -- node[below,pos=0.5] {|\textbackslash{}l\_@@\_xpos\_fp|} (c); % \end{tikzpicture} % \end{center} % The width and height of the box have dedicated parameters. % \begin{center} % \begin{tikzpicture}[scale=0.4,font=\footnotesize, % inner sep=1pt] % \draw[thick] (0,0) node[below right] {Screen canvas} rectangle (18,10); % \coordinate (m) at (12,5); % \coordinate (c) at ($(m)+(-3,2)$); % \draw[semithick] ($(m)-(3,2)$) node[below right] {Box} rectangle ($(m)+(3,2)$); % \fill (m) circle[radius=2pt]; % \draw[ultra thin] % (9,7) -- (9,8.1) % (15,7) -- (15,8.1); % \draw[<->] (9,8) -- node[above] {|\textbackslash{}l\_@@\_mediawidth\_fp|} (15,8); % \draw[ultra thin] % (9,3) -- (7.9,3) % (9,7) -- (7.9,7); % \draw[<->] (8,3) -- node[left] {|\textbackslash{}l\_@@\_mediaheight\_fp|} (8,7); % \end{tikzpicture} % \end{center} % The anchor of a box can be any of the main 8 wind directions (north, east, south, west, and the ones in between those). % This anchor location in combination with the width and height of the box, allow for a correction on the HTML coordinates. % The correction coefficients (relative to width and height) are: % % \begin{center} % \begin{tikzpicture}[scale=0.4,font=\footnotesize, % inner sep=1pt] % \draw[thick] (0,0) node[below right] {Screen canvas} rectangle (18,10); % \coordinate (m) at (12,5); % \coordinate (c) at ($(m)+(-3,2)$); % \draw[semithick,gray] ($(m)-(3,2)$) rectangle ($(m)+(3,2)$); % \foreach \x/\xpos in {0/left,0.5/,1/right} { % \foreach \y/\ypos in {0/above,0.5/above,1/below} { % \coordinate (p) at ($(c)+({\x*6},{-\y*4})$); % \node[font=\tiny,\ypos] at (p) {$({-\x},{-\y})$}; % \fill (p) circle[radius=2pt]; % } % } % \fill (m) circle[radius=2pt]; % \end{tikzpicture} % \end{center} % % \begin{macro}{\video} % \begin{macrocode} %<*reveal> \tl_new:N \l_@@_keyoverflow_tl \NewDocumentCommand\video{D<>{1-} O{} u{at} r() m}{ \only<#1> { % begin group to keep the key setting local \group_begin: \keys_set_exclude_groups:nnnN { beamerreveal / media } { animation } { #2 } \l_@@_keyoverflow_tl \tl_if_empty:NTF \l_@@_keyoverflow_tl {} { \msg_fatal:nne { beamerreveal / media } { illegal-keys-video } { \l_@@_keyoverflow_tl } } \dynamicContent_@@:nnn {#4} {#5} {video} \group_end: } } % % \end{macrocode} % \end{macro} % % \begin{macro}{\audio} % \begin{macrocode} %<*reveal> \NewDocumentCommand\audio{D<>{1-} O{} u{at} r() m}{ \only<#1> { % begin group to keep the key setting local \group_begin: \keys_set_exclude_groups:nnnN { beamerreveal / media } { animation } { #2 } \l_@@_keyoverflow_tl \tl_if_empty:NTF \l_@@_keyoverflow_tl {} { \msg_fatal:nne { beamerreveal / media } { illegal-keys-audio } { \l_@@_keyoverflow_tl } } \dynamicContent_@@:nnn {#4} {#5} {audio} \group_end: } } % % \end{macrocode} % \end{macro} % % \begin{macro}{\iframe} % \begin{macrocode} %<*reveal> \NewDocumentCommand\iframe{D<>{1-} O{} u{at} r() m}{ \only<#1> { % begin group to keep the key setting local \group_begin: \keys_set_exclude_groups:nnnN { beamerreveal / media } { dynamic animation } { #2 } \l_@@_keyoverflow_tl \tl_if_empty:NTF \l_@@_keyoverflow_tl {} { \msg_fatal:nne { beamerreveal / media } { illegal-keys-iframe } { \l_@@_keyoverflow_tl } } \dynamicContent_@@:nnn {#4} {#5} {iframe} \group_end: } } % % \end{macrocode} % %\end{macro} % % \begin{macro}{\image} % \begin{macrocode} %<*reveal> \NewDocumentCommand\image{D<>{1-} O{} u{at} r() m}{ \only<#1> { % begin group to keep the key setting local \group_begin: \keys_set_exclude_groups:nnnN { beamerreveal / media } { dynamic } { #2 } \l_@@_keyoverflow_tl \tl_if_empty:NTF \l_@@_keyoverflow_tl {} { \msg_fatal:nne { beamerreveal / media } { illegal-keys-image } { \l_@@_keyoverflow_tl } } \staticContent_@@:nnn {#4} {#5} {image} \group_end: } } % % \end{macrocode} % %\end{macro} % % \begin{macro}{\animation} % \begin{macrocode} %<*reveal> \NewDocumentCommand\animation{D<>{1-} O{} u{at} r() +m}{ \only<#1> { % begin group to keep the key setting local \group_begin: \keys_set_exclude_groups:nnnN { beamerreveal / media } { size, fit } { #2 } \l_@@_keyoverflow_tl \tl_if_empty:NTF \l_@@_keyoverflow_tl {} { \msg_fatal:nne { beamerreveal / media } { illegal-keys-animation } { \l_@@_keyoverflow_tl } } \fixedContent_@@:nnn {#4} {#5} {animation} \group_end: } } % % \end{macrocode} % \end{macro} % % \subsubsection{Auxiliary macros} % % \begin{macro}{\dynamicContent\_@@:nnn} % \begin{macrocode} %<*reveal> \cs_new:Npn \dynamicContent_@@:nnn #1#2#3 { % convert combination width/aspectratio to height, or % height/aspectratio to width \process_a_w_h_@@:NNN \l_@@_mediaaspectratio_fp \l_@@_mediawidth_fp \l_@@_mediaheight_fp % extract relative position from bottom left of page (0,0) to top right (1,1) \seq_set_split:Nnn \l_tmpa_seq { , } { #1 } \pgfmathsetmacro{\posx}{\seq_item:Nn \l_tmpa_seq {1}} \pgfmathsetmacro{\posy}{\seq_item:Nn \l_tmpa_seq {2}} % convert to html coordinates from top left corner, and correct for anchor location \fp_set:Nn \l_@@_xpos_fp { \posx + \l_@@_xposdelta_fp * \l_@@_mediawidth_fp } \fp_set:Nn \l_@@_ypos_fp { (1-\posy) + \l_@@_yposdelta_fp * \l_@@_mediaheight_fp } \writeliteral_@@:n { -#3: width={\fp_use:N \l_@@_mediawidth_fp}, height={\fp_use:N \l_@@_mediaheight_fp}, fit={\tl_use:N \l_@@_mediafit_tl}, background={\tl_use:N \l_@@_mediabackground_tl}, \bool_if:NTF \l_@@_mediaautoplay_bool {autoplay={},} {} \bool_if:NTF \l_@@_mediacontrols_bool {controls={},} {} \bool_if:NTF \l_@@_medialoop_bool {loop={},} {} \bool_if:NTF \l_@@_mediamuted_bool {muted={},} {} x={\fp_use:N \l_@@_xpos_fp}, y={\fp_use:N \l_@@_ypos_fp}, file={#2} } \bool_if:NTF \l_@@_mediaboxdraw_bool { \begin{tikzpicture}[overlay,remember~picture,font=\tiny] \extractloleft{$(current~page.south~west)$} \extractupright{$(current~page.north~east)$} \node[ anchor = \tl_use:N \l_@@_mediaanchor_tl, minimum~width={\fp_use:N \l_@@_mediawidth_fp * (\xupright - \xloleft)}, minimum~height={\fp_use:N \l_@@_mediaheight_fp * (\yupright - \yloleft)}, draw, fill=\tl_use:N \l_@@_mediabackground_tl, ] at ({\xloleft*(1-\posx)+\xupright*\posx},{\yloleft*(1-\posy)+\yupright*\posy}) {\textcolor{gray}{#2}}; \end{tikzpicture} }{} } % % \end{macrocode} % \end{macro} % % \begin{macro}{\staticContent\_@:nnn} % \begin{macrocode} %<*reveal> \cs_new:Npn \staticContent_@@:nnn #1#2#3 { % convert combination width/aspectratio to height, or % height/aspectratio to width \process_a_w_h_@@:NNN \l_@@_mediaaspectratio_fp \l_@@_mediawidth_fp \l_@@_mediaheight_fp % extract relative position from bottom left of page (0,0) to top right (1,1) \seq_set_split:Nnn \l_tmpa_seq { , } { #1 } \pgfmathsetmacro{\posx}{\seq_item:Nn \l_tmpa_seq {1}} \pgfmathsetmacro{\posy}{\seq_item:Nn \l_tmpa_seq {2}} % convert to html coordinates from top left corner, and correct for anchor location \fp_set:Nn \l_@@_xpos_fp { \posx + \l_@@_xposdelta_fp * \l_@@_mediawidth_fp } \fp_set:Nn \l_@@_ypos_fp { (1-\posy) + \l_@@_yposdelta_fp * \l_@@_mediaheight_fp } \writeliteral_@@:n { -#3: width={\fp_use:N \l_@@_mediawidth_fp}, height={\fp_use:N \l_@@_mediaheight_fp}, fit={\tl_use:N \l_@@_mediafit_tl}, background={\tl_use:N \l_@@_mediabackground_tl}, \bool_if:NTF \l_@@_mediaautoplay_bool {autoplay={true},} {} x={\fp_use:N \l_@@_xpos_fp}, y={\fp_use:N \l_@@_ypos_fp}, file={#2} } \bool_if:NTF \l_@@_mediaboxdraw_bool { \begin{tikzpicture}[overlay,remember~picture,font=\tiny] \extractloleft{$(current~page.south~west)$} \extractupright{$(current~page.north~east)$} \node[ anchor = \tl_use:N \l_@@_mediaanchor_tl, minimum~width={\fp_use:N \l_@@_mediawidth_fp * (\xupright - \xloleft)}, minimum~height={\fp_use:N \l_@@_mediaheight_fp * (\yupright - \yloleft)}, draw, fill=\tl_use:N \l_@@_mediabackground_tl, ] at ({\xloleft*(1-\posx)+\xupright*\posx},{\yloleft*(1-\posy)+\yupright*\posy}) {\textcolor{gray}{#2}}; \end{tikzpicture} }{} } % % \end{macrocode} % \end{macro} % % \begin{macro}{\fixedContent\_@@:nnn} % \begin{macrocode} %<*reveal> \cs_new:Npn \fixedContent_@@:nnn #1#2#3 { % first create the box with the content and measure it \pgfmathsetmacro\progress{ \fp_use:N \l_@@_mediapdfprogress_fp }% \hbox_set:Nn \l_tmpa_box {#2} \fp_set:Nn \l_tmpa_fp { \dim_eval:n { \box_wd:N \l_tmpa_box } } \fp_set:Nn \l_tmpb_fp { \dim_eval:n { \pagewidth } } \fp_set:Nn \l_@@_mediawidth_fp { \fp_eval:n { \l_tmpa_fp / \l_tmpb_fp } } \fp_set:Nn \l_tmpa_fp { \dim_eval:n { \box_ht:N \l_tmpa_box } } \fp_set:Nn \l_tmpb_fp { \dim_eval:n { \pageheight } } \fp_set:Nn \l_@@_mediaheight_fp { \fp_eval:n { \l_tmpa_fp / \l_tmpb_fp } } % extract relative position from bottom left of page (0,0) to top right (1,1) \seq_set_split:Nnn \l_tmpa_seq { , } { #1 } \pgfmathsetmacro{\posx}{\seq_item:Nn \l_tmpa_seq {1}} \pgfmathsetmacro{\posy}{\seq_item:Nn \l_tmpa_seq {2}} % convert to html coordinates from top left corner, and correct for anchor location \fp_set:Nn \l_@@_xpos_fp { \posx + \l_@@_xposdelta_fp * \l_@@_mediawidth_fp } \fp_set:Nn \l_@@_ypos_fp { (1-\posy) + \l_@@_yposdelta_fp * \l_@@_mediaheight_fp } \writeliteral_@@:n { -#3: width={ \fp_use:N \l_@@_mediawidth_fp }, height={ \fp_use:N \l_@@_mediaheight_fp }, framerate={ \fp_use:N \l_@@_mediaframerate_fp }, duration={ \fp_use:N \l_@@_mediaduration_fp }, x={\fp_use:N \l_@@_xpos_fp}, y={\fp_use:N \l_@@_ypos_fp}, fit={fit}, background={\tl_use:N \l_@@_mediabackground_tl}, \bool_if:NTF \l_@@_mediaautoplay_bool {autoplay={},} {} \bool_if:NTF \l_@@_medialoop_bool {loop={},} {} \bool_if:NTF \l_@@_mediacontrols_bool {controls={},} {} } \begin{tikzpicture}[overlay,remember~picture,font=\tiny] \extractloleft{$(current~page.south~west)$} \extractupright{$(current~page.north~east)$} \node at ({\xloleft*(1-\posx)+\xupright*\posx},{\yloleft*(1-\posy)+\yupright*\posy}) {\box_use:N \l_tmpa_box}; \end{tikzpicture} \writeraw_@@:n { #2 } } % % \end{macrocode} % \end{macro} % % \subsection{Postamble} % % \begin{macrocode} %<*reveal> \AtEndDocument{ \ExplSyntaxOn \iow_close:N \g_@@_rvlfile \ExplSyntaxOff } % % \end{macrocode} % \clearpage % % \bibliographystyle{alpha} % % \begin{thebibliography}{99} % % \bibitem{beamer} % Till Tantau et al., "beamer - A \LaTeX{} class for producing % presentations and slides", % \newblock \url{https://ctan.org/pkg/beamer}, % \newblock online, accessed in December 2025. % \bibitem{movie15} % Alexander Grahn, "movie15 - Multimedia inclusion package", % \newblock \url{https://ctan.org/pkg/movie15}, % \newblock online, accessed in December 2025. % \bibitem{media9} % Alexander Grahn, "media9 - Multimedia inclusion package with Adobe Reader-9/X compatibility", % \newblock \url{https://ctan.org/pkg/media9}, % \newblock online, accessed in December 2025. % \bibitem{manim} % Grant Sanderson, "manim - A community maintained Python library for creating mathematical animations", % \newblock \url{https://www.manim.community}, % \newblock online, accessed in December 2025. % \bibitem{pdfcrop} % Heiko Oberdiek, "pdfcrop --- Crop PDF graphics", % \newblock \url{https://ctan.org/pkg/pdfcrop}, % \newblock online, accessed in December 2025. % \bibitem{pdftoppm} % Poppler developers, "Poppler Utilities (pdftoppm)", % \newblock \url{https://poppler.freedesktop.org}, % \newblock oline, accessed in December 2025. % \bibitem{ffmpeg} % FFmpeg developers, "ffmpeg tool", % \newblock \url{https://ffmpeg.org}, % \newblock oline, accessed in December 2025. % \end{thebibliography} % % \Finale \endinput