added image in qr-code or next to name

This commit is contained in:
Marc Wäckerlin
2025-11-08 17:09:38 +01:00
parent a43e21e3b2
commit 9c4d85528a
5 changed files with 122 additions and 40 deletions
+85 -39
View File
@@ -20,7 +20,12 @@
\DeclareStringOption[1]{cutlen}
\DeclareStringOption[0.50]{textwidth}
\DeclareStringOption[0.40]{qrwidth}
\DeclareStringOption[Q]{qreclevel} % QR code error correction level (L,M,Q,H) default Q
\DeclareStringOption[0.15]{qrlogoscale} % relative size of logo in QR code (0-1), default 0.15 = 15%
\DeclareStringOption[0.02]{qrlogoborder} % white padding around the photo overlay in QR code
\DeclareStringOption[de]{lang}
\DeclareBoolOption[false]{ioscrlf} % use CRLF line endings in vCard (iOS compatibility); default off to avoid pdfTeX issues
\DeclareBoolOption[false]{photoinqr} % if true: photo goes in QR center; if false (default): photo next to name
\DeclareBoolOption[true]{address}
\DeclareComplementaryOption{noaddress}{address}
\DeclareBoolOption[true]{hint}
@@ -66,6 +71,8 @@
\RequirePackage{DejaVuSans}
\RequirePackage[T1]{fontenc}
\RequirePackage{wrapfig}
\RequirePackage{graphicx} % needed for optional photo
\RequirePackage{tikz} % needed for logo overlay in QR code
\RequirePackage[\content,top=\padding,left=\padding,right=\padding,bottom=\padding]{geometry}
%\RequirePackage{pbox}
\RequirePackage{varwidth}
@@ -117,6 +124,7 @@
\registerData{google}
\registerData{pgpurl}
\registerData{pgpfingerprint}
\registerData{photo} % path to photo file for display next to name
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -142,36 +150,46 @@
% name - assemble full name from the parts, such as Xgivennames and Xfamilynames
\newcommand\name{\ifexists{Xhonoricprefix}{\Xhonoricprefix\ }\ifexists{Xgivennames}{\Xgivennames\ }\ifexists{Xfamilynames}{\Xfamilynames}\ifexists{Xhonoricsuffix}{\ \Xhonoricsuffix}}
% internal box for measuring name height when photo is present
\newsavebox{\BCQ@namebox}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% vcard - the content of the vcard
\newcommand\vcard{BEGIN:VCARD^^J
VERSION:4.0^^J
N:\cond{Xfamilynames};\cond{Xgivennames};\cond{Xadditionalnames};\cond{Xhonoricprefix};\cond{Xhonoricsuffix}^^J
FN:\name\ifexists{Xadditionalnames}{\ifcsempty{name}{}{\ }\Xadditionalnames}^^J
\ifexists{printaddress}{ADR\ifexists{Xtype}{;TYPE=\Xtype}:\cond{Xpobox};\cond{Xextaddr};\cond{Xstreet};\cond{Xcity};\cond{Xregion};\cond{Xzip};\cond{Xcountry}^^J}
\ifexists{Xphone}{TEL;VALUE=uri;TYPE=\ifexists{Xtype}{\Xtype,}voice,text:tel:\Xphone^^J}
\ifexists{Xemail}{EMAIL\ifexists{Xtype}{;TYPE=\Xtype}:\Xemail^^J}
\ifexists{Xjabber}{IMPP;TYPE=XMPP:\Xjabber^^J}
\ifexists{Xmatrixorg}{IMPP;TYPE=MATRIX:\Xmatrixorg^^J}
\ifexists{Xcloud}{URL:https://nextcloud.com/federation/\#\Xcloud^^J}
\ifexists{Xhomepage}{URL:https://\Xhomepage^^J}
\ifexists{Xwordpress}{URL:https://\Xwordpress^^J}
\ifexists{Xdrupal}{URL:https://\Xdrupal^^J}
\ifexists{Xjoomla}{URL:https://\Xjoomla^^J}
\ifexists{Xwikipedia}{URL:https://\lang.wikipedia.org/wiki/\Xwikipedia^^J}
\ifexists{Xlink}{URL:https://\Xlink^^J}
\ifexists{Xworld}{URL:https://\Xworld^^J}
\ifexists{Xgit}{URL:https://\Xgit^^J}
\ifexists{Xgitea}{URL:https://\Xgitea^^J}
\ifexists{Xgithub}{URL:https://github.com/\Xgithub^^J}
\ifexists{Xfacebook}{URL:https://facebook.com/\Xfacebook^^J}
\ifexists{Xtwitter}{URL:https://twitter.com/\Xtwitter^^J}
\ifexists{Xyoutube}{URL:https://youtube.com/user/\Xyoutube^^J}
\ifexists{Xgoogle}{URL:https://plus.google.com/+\Xgoogle^^J}
\ifexists{Xpgpurl}{KEY;MEDIATYPE=application/pgp-keys:\Xpgpurl^^J}
\ifexists{Xpgpfingerprint}{KEY:data:application/x-pgp-fingerprint,\Xpgpfingerprint^^J}
END:VCARD^^J}
% newline selection: default LF (robust for qrcode). Optional CRLF if ioscrlf option set.
\ifBCQ@ioscrlf
\def\BCQ@nl{\char13\char10}% CRLF
\else
\def\BCQ@nl{^^J}% LF only
\fi
% vcard assembly (version 4.0 retained). CRLF improves iOS import robustness.
\newcommand\vcard{BEGIN:VCARD\BCQ@nl
VERSION:4.0\BCQ@nl
N:\cond{Xfamilynames};\cond{Xgivennames};\cond{Xadditionalnames};\cond{Xhonoricprefix};\cond{Xhonoricsuffix}\BCQ@nl
FN:\name\ifexists{Xadditionalnames}{\ifcsempty{name}{} { }\Xadditionalnames}\BCQ@nl
\ifexists{printaddress}{ADR\ifexists{Xtype}{;TYPE=\Xtype}:\cond{Xpobox};\cond{Xextaddr};\cond{Xstreet};\cond{Xcity};\cond{Xregion};\cond{Xzip};\cond{Xcountry}\BCQ@nl}
\ifexists{Xphone}{TEL;VALUE=uri;TYPE=\ifexists{Xtype}{\Xtype,}voice,text:tel:\Xphone\BCQ@nl}
\ifexists{Xemail}{EMAIL\ifexists{Xtype}{;TYPE=\Xtype}:\Xemail\BCQ@nl}
\ifexists{Xjabber}{IMPP;TYPE=XMPP:\Xjabber\BCQ@nl}
\ifexists{Xmatrixorg}{IMPP;TYPE=MATRIX:\Xmatrixorg\BCQ@nl}
\ifexists{Xcloud}{URL:https://nextcloud.com/federation/\#\Xcloud\BCQ@nl}
\ifexists{Xhomepage}{URL:https://\Xhomepage\BCQ@nl}
\ifexists{Xwordpress}{URL:https://\Xwordpress\BCQ@nl}
\ifexists{Xdrupal}{URL:https://\Xdrupal\BCQ@nl}
\ifexists{Xjoomla}{URL:https://\Xjoomla\BCQ@nl}
\ifexists{Xwikipedia}{URL:https://\lang.wikipedia.org/wiki/\Xwikipedia\BCQ@nl}
\ifexists{Xlink}{URL:https://\Xlink\BCQ@nl}
\ifexists{Xworld}{URL:https://\Xworld\BCQ@nl}
\ifexists{Xgit}{URL:https://\Xgit\BCQ@nl}
\ifexists{Xgitea}{URL:https://\Xgitea\BCQ@nl}
\ifexists{Xgithub}{URL:https://github.com/\Xgithub\BCQ@nl}
\ifexists{Xfacebook}{URL:https://facebook.com/\Xfacebook\BCQ@nl}
\ifexists{Xtwitter}{URL:https://twitter.com/\Xtwitter\BCQ@nl}
\ifexists{Xyoutube}{URL:https://youtube.com/user/\Xyoutube\BCQ@nl}
\ifexists{Xgoogle}{URL:https://plus.google.com/+\Xgoogle\BCQ@nl}
\ifexists{Xpgpurl}{KEY;MEDIATYPE=application/pgp-keys:\Xpgpurl\BCQ@nl}
\ifexists{Xpgpfingerprint}{KEY:data:application/x-pgp-fingerprint,\Xpgpfingerprint\BCQ@nl}
END:VCARD\BCQ@nl}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -233,7 +251,24 @@ END:VCARD^^J}
%\frame
{
\begin{minipage}[c][\heightscale][c]{\imagepercents\textwidth}
\qrcode[level=Q,version=0,height=\textwidth]{\vcard}
\ifBCQ@photoinqr
% QR code with photo overlay in center
\ifcsdef{Xphoto}{%
\begin{tikzpicture}
\node[inner sep=0pt] (qr) {\qrcode[level=\BCQ@qreclevel,version=0,height=\textwidth]{\vcard}};
% White padding behind the photo to improve readability
\node[fill=white, rounded corners=0.5pt, inner sep=\BCQ@qrlogoborder\textwidth] at (qr.center) {%
\includegraphics[width=\BCQ@qrlogoscale\textwidth]{\Xphoto}%
};
\end{tikzpicture}%
}{%
% No photo defined, just show QR code
\qrcode[level=\BCQ@qreclevel,version=0,height=\textwidth]{\vcard}%
}
\else
% Standard QR code without overlay
\qrcode[level=\BCQ@qreclevel,version=0,height=\textwidth]{\vcard}
\fi
\end{minipage}
}
}
@@ -242,17 +277,28 @@ END:VCARD^^J}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% insertname - insert the name on the top
\newcommand\insertname{
%\frame
%\begin{minipage}{\textwidth}
%\pbox[t]{0.9\textwidth}
{\bfseries
\cond{name}
\cond{Xadditionalnames}
}
%\end{minipage}
% typeset name into box for measurement
\sbox{\BCQ@namebox}{\bfseries\cond{name}\ifexists{Xadditionalnames}{\ifcsempty{name}{} { }\Xadditionalnames}}%
\ifcsdef{Xphoto}{% photo defined
\ifBCQ@photoinqr
% Photo in QR code: show name only, same structure as no-photo case
{\bfseries\usebox{\BCQ@namebox}}%
\else
% Photo next to name: two-column layout (photo | name)
\begin{minipage}{\textwidth}
\begin{minipage}[c]{0.30\textwidth}% photo column (increased from 0.22)
\includegraphics[height=\dimexpr\ht\BCQ@namebox+\dp\BCQ@namebox\relax]{\Xphoto}% scaled to name height
\end{minipage}
\hfill
\begin{minipage}[c]{0.67\textwidth}% name column (adjusted from 0.75)
\ifBCQ@rightalign\raggedleft\fi% apply alignment
{\bfseries\usebox{\BCQ@namebox}}%
\end{minipage}
\end{minipage}
\fi
}{% no photo: just name
{\bfseries\usebox{\BCQ@namebox}}%
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%