Add automatic slide partner logos and refresh LaTeX devcontainer

This commit is contained in:
khannurien
2026-10-11 11:58:39 +00:00
parent 949dfbe414
commit f68b9b647d
21 changed files with 980 additions and 98 deletions

77
Slides/README.md Normal file
View File

@@ -0,0 +1,77 @@
# Slides
Compile `slides.tex` with LuaLaTeX (and Biber for references).
## Partner and funding logos
Enable partners in the preamble, in the desired display order:
```latex
\partner{labsticc}\partner{ubo}\partner{aid}\partner{ifremer}
```
Logos for the following partners are included in `img/partners/`:
| Identifier | Partner |
| --- | --- |
| `labsticc` | Lab-STICC |
| `ubo` | Université de Bretagne Occidentale |
| `ensta` | ENSTA, Institut Polytechnique de Paris |
| `aid` | Agence de l'innovation de défense |
| `ifremer` | Ifremer |
| `lip6` | Laboratoire d'informatique de Sorbonne Université |
| `sorbonne` | Sorbonne Université |
| `academia-sinica` | Academia Sinica |
| `taipei` | University of Taipei |
For example, enable the additional four with:
```latex
\partner{lip6}\partner{sorbonne}\partner{academia-sinica}\partner{taipei}
```
Enable ENSTA with `\partner{ensta}`.
Asset sources are recorded in [`img/partners/README.md`](img/partners/README.md).
Add other individual logos in `img/partners/`, named after their identifier:
```text
img/partners/labsticc.png
img/partners/ubo.png
img/partners/aid.png
img/partners/ifremer.png
```
PNG, PDF, JPG and JPEG are supported, searched in that order. All nine bundled
assets are transparent PNGs. Prefer high-resolution transparent PNGs or vector
PDFs, tightly cropped to the artwork;
embedded white space counts towards a logo's dimensions. SVGs should first be
exported to PDF. The existing `img/logos.png` is a combined UBO/Lab-STICC image,
not two independently selectable logos.
For other file locations or identifiers, register a path (with or without its
extension) and then enable the partner:
```latex
\declarepartner{my-funder}{img/custom-funder.pdf}
\partner{my-funder}
```
The title page places the logos at the bottom right, inside the theme's margins.
Column count, logo sizes, cell sizes, spacing and row wrapping are computed from
the number of available logos, their aspect ratios, the column width and the
slide height. Logos have equal bounding-box area for comparable visual weight:
wide wordmarks are shorter than square seals, rather than dominating the block.
Aspect ratios are preserved; logos are centred within evenly spaced grid cells.
The final row is right-aligned and stays within a bounded title-page area.
Repeated selections are ignored. Missing files produce warnings and are skipped,
without inserting placeholder logos. Partners do not appear on ordinary slides.
With no partners selected, the existing `\titlegraphic{...}` is still used.
When partners are selected, they replace the legacy title graphic.
### Additional information
No additional logo files are needed for the nine included partners. If a funder
requires a specific logo variant, minimum size, ordering or acknowledgement text,
provide those project-specific requirements. No manual layout dimensions are needed.

View File

@@ -0,0 +1,30 @@
# Partner logo sources
Downloaded from official institutional websites on 2026-10-11. Logos remain the
property of their respective institutions; availability here does not grant
unrestricted use or imply endorsement. Follow the applicable branding rules.
| File | Official asset source |
| --- | --- |
| `labsticc.png` | [IMT Atlantique / Lab-STICC](https://www.imt-atlantique.fr/sites/default/files/users/user1867/logo-lab-sticc.png) |
| `ubo.png` | Official inline SVG labelled `Logo UBO` on [UBO's branding page](https://www.univ-brest.fr/fr/page/charte-graphique-ubo-et-logos-disposition-des-partenaires), rendered to a transparent 3,161 × 1,299 PNG at 600 DPI |
| `ensta.png` | Official blue vertical ENSTA / IP Paris transparent PNG (`Ensta-logotype-05-bleu-rvb.png`) from the [ENSTA RGB logo archive](https://www.ensta.fr/sites/default/files/content/article/pdf/LogoENSTA_RVB.zip), linked from [ENSTA's branding page](https://www.ensta.fr/logo-et-charte-graphique); cropped to 3,638 × 2,286 pixels |
| `aid.png` | [Ministère des Armées / AID](https://www.defense.gouv.fr/sites/default/files/aid/logo.png), displayed on [AID's RAPID page](https://www.defense.gouv.fr/aid/deposez-votre-projet/rapid-regime-dappui-linnovation-duale) |
| `ifremer.png` | Inline `logo-ifremer` SVG from [Ifremer](https://www.ifremer.fr/fr); rendered using the site's brand colour `#0032c6` |
| `lip6.png` | Inline `LIP6` SVG from [LIP6](https://www.lip6.fr/); rendered using `--LIP6_logo_color: #25314F` from the site's `css/common.css` |
| `sorbonne.png` | [Sorbonne Université SVG](https://www.sorbonne-universite.fr/sites/default/files/media/2019-10/logo_4.svg), rendered to PNG |
| `academia-sinica.png` | [Academia Sinica](https://www.sinica.edu.tw/images/AS_logo_2.png), referenced by its [official website](https://www.sinica.edu.tw/en) |
| `taipei.png` | [University of Taipei masthead](https://www.utaipei.edu.tw/var/file/0/1000/img/1583/366369593.jpg), linked from its [official website](https://www.utaipei.edu.tw/) |
All nine files are tightly cropped RGBA PNGs with actual transparent pixels,
not just an alpha channel containing an opaque white background. Existing alpha
was preserved. For opaque sources, only white background connected to the outer
edge was removed; white artwork inside the Academia Sinica seal was retained,
and antialiased contour pixels were unmatted to avoid white fringes.
The SVG-derived assets were rendered at high resolution (at least 1,900 pixels
wide). UBO was re-rendered from vector paths, not upscaled from the old 489-pixel
PNG; its SVG viewport was extended to preserve the descender in “Bretagne”.
LIP6's white circular website backdrop was omitted, keeping the plain
logotype; glyph paths, proportions and lettering were not changed. Compilation
needs no SVG converter, network access or additional shell commands.

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

BIN
Slides/img/partners/aid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 KiB

BIN
Slides/img/partners/ubo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

202
Slides/slides-partners.sty Normal file
View File

@@ -0,0 +1,202 @@
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{slides-partners}[2026/10/11 Automatic title-page partner logos]
\RequirePackage{graphicx}
\RequirePackage{expl3}
\RequirePackage{xparse}
\ExplSyntaxOn
\seq_new:N \g__slides_partners_seq
\prop_new:N \g__slides_partner_files_prop
\seq_new:N \l__slides_partner_files_seq
\seq_new:N \l__slides_partner_ratios_seq
\box_new:N \l__slides_partner_box
\tl_new:N \l__slides_partner_file_tl
\tl_new:N \l__slides_partner_resolved_tl
\int_new:N \l__slides_partner_count_int
\int_new:N \l__slides_partner_columns_int
\int_new:N \l__slides_partner_rows_int
\fp_new:N \l__slides_partner_minratio_fp
\fp_new:N \l__slides_partner_maxratio_fp
\fp_new:N \l__slides_partner_candidate_fp
\fp_new:N \l__slides_partner_scale_fp
\dim_new:N \l__slides_partner_width_dim
\dim_new:N \l__slides_partner_maxheight_dim
\dim_new:N \l__slides_partner_xgap_dim
\dim_new:N \l__slides_partner_ygap_dim
\dim_new:N \l__slides_partner_cellwidth_dim
\dim_new:N \l__slides_partner_cellheight_dim
% Selection is ordered and idempotent. File lookup is delayed until rendering,
% so a declaration can appear before or after its corresponding selection.
\NewDocumentCommand{\partner}{m}
{
\seq_if_in:NnF \g__slides_partners_seq {#1}
{ \seq_gput_right:Nn \g__slides_partners_seq {#1} }
}
\NewDocumentCommand{\declarepartner}{mm}
{ \prop_gput:Nnn \g__slides_partner_files_prop {#1} {#2} }
\cs_new_protected:Npn \__slides_partners_collect:
{
\seq_clear:N \l__slides_partner_files_seq
\seq_clear:N \l__slides_partner_ratios_seq
\seq_map_inline:Nn \g__slides_partners_seq
{
\prop_get:NnNF \g__slides_partner_files_prop {##1}
\l__slides_partner_file_tl
{ \tl_set:Nn \l__slides_partner_file_tl {img/partners/##1} }
\tl_clear:N \l__slides_partner_resolved_tl
\file_if_exist:VTF \l__slides_partner_file_tl
{ \tl_set_eq:NN \l__slides_partner_resolved_tl \l__slides_partner_file_tl }
{
\clist_map_inline:nn {png,pdf,jpg,jpeg}
{
\file_if_exist:nT {\l__slides_partner_file_tl .####1}
{
\tl_set:Nx \l__slides_partner_resolved_tl
{\l__slides_partner_file_tl .####1}
\clist_map_break:
}
}
}
\tl_if_empty:NTF \l__slides_partner_resolved_tl
{
\PackageWarning{slides-partners}
{Logo~for~partner~`##1'~not~found~at~
`\tl_use:N \l__slides_partner_file_tl'.~Skipping~it}
}
{
\seq_put_right:NV \l__slides_partner_files_seq
\l__slides_partner_resolved_tl
\hbox_set:Nn \l__slides_partner_box
{ \includegraphics{\tl_use:N \l__slides_partner_resolved_tl} }
\seq_put_right:Nx \l__slides_partner_ratios_seq
{
\fp_eval:n
{ \dim_to_fp:n {\box_wd:N \l__slides_partner_box} /
\dim_to_fp:n {\box_ht:N \l__slides_partner_box +
\box_dp:N \l__slides_partner_box} }
}
}
}
}
% Equal-area logos in equal-width cells give seals and wide wordmarks comparable
% visual weight. Try every column count, maximizing the common area scale while
% fitting the tallest and widest logos into the available title-page rectangle.
\cs_new_protected:Npn \__slides_partners_layout:
{
\int_set:Nn \l__slides_partner_count_int
{ \seq_count:N \l__slides_partner_files_seq }
\dim_set:Nn \l__slides_partner_width_dim {\linewidth}
\dim_set:Nn \l__slides_partner_maxheight_dim {.24\paperheight}
\dim_set:Nn \l__slides_partner_xgap_dim
{ \fp_to_dim:n {min(.04 * \dim_to_fp:n {\linewidth},
.25 * \dim_to_fp:n {\linewidth} / max(1,\l__slides_partner_count_int-1))} }
\dim_set:Nn \l__slides_partner_ygap_dim
{ \fp_to_dim:n {min(.015 * \dim_to_fp:n {\paperheight},
.25 * \dim_to_fp:n {\l__slides_partner_maxheight_dim} /
max(1,\l__slides_partner_count_int-1))} }
\fp_set:Nn \l__slides_partner_minratio_fp {inf}
\fp_zero:N \l__slides_partner_maxratio_fp
\seq_map_inline:Nn \l__slides_partner_ratios_seq
{
\fp_set:Nn \l__slides_partner_minratio_fp
{min(\l__slides_partner_minratio_fp,##1)}
\fp_set:Nn \l__slides_partner_maxratio_fp
{max(\l__slides_partner_maxratio_fp,##1)}
}
\fp_zero:N \l__slides_partner_scale_fp
\int_set:Nn \l__slides_partner_columns_int {1}
\int_step_inline:nnnn {\l__slides_partner_count_int} {-1} {1}
{
\int_set:Nn \l__slides_partner_rows_int
{ \fp_eval:n {ceil(\l__slides_partner_count_int / ##1)} }
\fp_set:Nn \l__slides_partner_candidate_fp
{ min(.14 * \dim_to_fp:n {\paperheight},
(\dim_to_fp:n {\l__slides_partner_maxheight_dim} -
(\l__slides_partner_rows_int-1) *
\dim_to_fp:n {\l__slides_partner_ygap_dim}) /
\l__slides_partner_rows_int * sqrt(\l__slides_partner_minratio_fp),
(\dim_to_fp:n {\l__slides_partner_width_dim} -
(##1-1) * \dim_to_fp:n {\l__slides_partner_xgap_dim}) /
##1 / sqrt(\l__slides_partner_maxratio_fp)) }
% Break equal-size ties by minimizing unused cells in the final row.
\fp_compare:nT
{ \l__slides_partner_candidate_fp > \l__slides_partner_scale_fp + .0001 ||
(abs(\l__slides_partner_candidate_fp - \l__slides_partner_scale_fp) <= .0001 &&
##1 * \l__slides_partner_rows_int <
\l__slides_partner_columns_int *
ceil(\l__slides_partner_count_int / \l__slides_partner_columns_int)) }
{
\fp_set_eq:NN \l__slides_partner_scale_fp \l__slides_partner_candidate_fp
\int_set:Nn \l__slides_partner_columns_int {##1}
}
}
% Size cells to the widest rendered logo, not the entire available column.
% The enclosing row still right-aligns the compact grid in the title footer.
\dim_set:Nn \l__slides_partner_cellwidth_dim
{ \fp_to_dim:n {\l__slides_partner_scale_fp * sqrt(\l__slides_partner_maxratio_fp)} }
\dim_set:Nn \l__slides_partner_cellheight_dim
{ \fp_to_dim:n {\l__slides_partner_scale_fp / sqrt(\l__slides_partner_minratio_fp)} }
}
\cs_new_protected:Npn \__slides_partners_typeset:
{
\vbox
{
\offinterlineskip
\int_step_inline:nn {\l__slides_partner_count_int}
{
\int_compare:nNnT
{\int_mod:nn {##1-1} {\l__slides_partner_columns_int}} = {0}
{
\int_compare:nNnT {##1} > {1}
{ \vskip \l__slides_partner_ygap_dim }
\hbox_to_wd:nn {\l__slides_partner_width_dim}
{
\hfil
\int_step_inline:nnn {##1}
{\int_min:nn {##1+\l__slides_partner_columns_int-1}
{\l__slides_partner_count_int}}
{
\int_compare:nNnT {####1} > {##1}
{ \hskip \l__slides_partner_xgap_dim }
\vbox_to_ht:nn {\l__slides_partner_cellheight_dim}
{
\vfil
\hbox_to_wd:nn {\l__slides_partner_cellwidth_dim}
{
\hfil
\includegraphics[height=\fp_to_dim:n
{\l__slides_partner_scale_fp / sqrt(
\seq_item:Nn \l__slides_partner_ratios_seq {####1})}]
{\seq_item:Nn \l__slides_partner_files_seq {####1}}
\hfil
}
\vfil
}
}
}
}
}
}
}
\NewDocumentCommand{\insertpartnerlogos}{}
{
\group_begin:
\seq_if_empty:NTF \g__slides_partners_seq
{ \inserttitlegraphic } % Backwards compatibility with existing slides.
{
\__slides_partners_collect:
\seq_if_empty:NF \l__slides_partner_files_seq
{
\__slides_partners_layout:
\__slides_partners_typeset:
}
}
\group_end:
}
\ExplSyntaxOff
\endinput

View File

@@ -170,6 +170,7 @@
\RequirePackage{amsmath,amssymb,amsfonts}
% resizebox
\RequirePackage{graphicx}
\RequirePackage{slides-partners}
\RequirePackage{subcaption}
% tables
\RequirePackage{tabularx}
@@ -199,36 +200,24 @@
% https://ctan.math.illinois.edu/macros/latex/contrib/beamer-contrib/themes/moloch/moloch.pdf
\makeatletter
\setbeamertemplate{title page}{
\begin{minipage}[b][\paperheight]{\textwidth}
% \vfill%
% Use the theme's margins rather than a full-paper-height box, which placed
% the footer almost on the page edge. Stretch only the space above the footer.
\begin{minipage}[t][\dimexpr\paperheight-2\beamer@leftmargin\relax][s]{\textwidth}
\vspace*{.04\paperheight}
\ifx\inserttitle\@empty\else\usebeamertemplate*{title}\fi
\ifx\insertsubtitle\@empty\else\usebeamertemplate*{subtitle}\fi
\vspace{.2cm}
\ifx\insertdate\@empty\else\usebeamertemplate*{date}\fi
\usebeamertemplate*{title separator}
\vspace{-.2cm}
\begin{columns}[]
\column{0.4\linewidth}
\ifx\beamer@shortauthor\@empty\else\usebeamertemplate*{author}\fi
\column{0.4\linewidth}
% \begin{table}[]
% \begin{flushleft}
% \small
% \begin{tabular}{ll}
% Rapporteur & Blabla \\
% Rapporteur & Blabla
% \end{tabular}
% \end{flushleft}
% \end{table}
\end{columns}
\begin{columns}[b]
\column{0.4\linewidth}
\ifx\beamer@shortauthor\@empty\else\usebeamertemplate*{author}\fi
\vfill
\begin{columns}[b,onlytextwidth]
\column{0.52\linewidth}
\ifx\insertinstitute\@empty\else\usebeamertemplate*{institute}\fi
\column{0.5\linewidth}
\vspace{-2cm}
\ifx\inserttitlegraphic\@empty\else\inserttitlegraphic\fi
\column{0.44\linewidth}
\insertpartnerlogos
\end{columns}
\vspace*{.2cm}
\vspace*{.02\paperheight}
\end{minipage}
}
\makeatother

View File

@@ -4,20 +4,28 @@
\title{Présentation}
\subtitle{À propos de...}
\date{\today}
\titlegraphic{\flushright\includegraphics[height=1.3cm]{img/logos.png}\vspace{.5cm}}
% Enable partners in display order; logo layout and dimensions are automatic.
\partner{aid}
\partner{labsticc}
\partner{ubo}
\partner{ensta}
% \partner{ifremer}
% \partner{lip6}
% \partner{sorbonne}
% \partner{academia-sinica}
% \partner{taipei}
% See README.md for supported formats and custom logo paths.
% Optional legacy title graphic (used only when no partners are enabled):
% \titlegraphic{\flushright\includegraphics[height=1.3cm]{img/logos.png}\vspace{.5cm}}
\author{
\texorpdfstring{
\begin{table}[]
\begin{flushleft}
\begin{tabular}{ll}
& Vincent Lannurien~\inst{1} \\
& Laurent Lemarchand~\inst{1} \\
& Abdel Malek Toumi~\inst{2} \\
& Jalil Boukhobza~\inst{2}
\end{tabular}
\end{flushleft}
\end{table}
\begin{tabular}{@{}l@{}}
Vincent Lannurien~\inst{1} \\
Laurent Lemarchand~\inst{1} \\
Abdel Malek Toumi~\inst{2} \\
Jalil Boukhobza~\inst{2}
\end{tabular}
}
{
Vincent Lannurien \and
@@ -29,19 +37,13 @@
\institute{
\texorpdfstring{
\begin{table}[]
\centering
\begin{flushleft}
\begin{tabular}{L}
\inst{1}~Lab-STICC, CNRS UMR 6285, Université de Bretagne Occidentale, Brest
\inst{2}~Lab-STICC, CNRS UMR 6285, ENSTA, Institut Polytechnique de Paris, Brest \\
\end{tabular}
\end{flushleft}
\end{table}
\raggedright
\inst{1}~Lab-STICC, CNRS, UMR 6285, Université de Bretagne Occidentale, Brest\par\medskip
\inst{2}~Lab-STICC, CNRS, UMR 6285, ENSTA, Institut Polytechnique de Paris, Brest
}
{
Lab-STICC, CNRS UMR 6285, ENSTA, Institut Polytechnique de Paris, Brest \and
Lab-STICC, CNRS UMR 6285, Université de Bretagne Occidentale, Brest
Lab-STICC, CNRS, UMR 6285, ENSTA, Institut Polytechnique de Paris, Brest \and
Lab-STICC, CNRS, UMR 6285, Université de Bretagne Occidentale, Brest
}
}