% Author: Marc Wäckerlin % License: LGPL \NeedsTeXFormat{LaTeX2e} \ProvidesClass{businesscard-qrcode}[2018/08/15 version 1.2 ready for ctan] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % option evaluation \RequirePackage{kvoptions} \SetupKeyvalOptions{ family=BCQ, prefix=BCQ@ } \DeclareStringOption[89mm]{paperwidth} \DeclareStringOption[59mm]{paperheight} \DeclareStringOption[85mm]{contentwidth} \DeclareStringOption[55mm]{contentheight} \DeclareStringOption[8pt]{fontsize} \DeclareStringOption[2mm]{padding} \DeclareStringOption[2]{cutdist} \DeclareStringOption[1]{cutlen} \DeclareStringOption[0.50]{textwidth} \DeclareStringOption[0.40]{qrwidth} \DeclareStringOption[H]{qreclevel} % QR code error correction level (L,M,Q,H) \DeclareStringOption[0.25]{qrlogoscale} % logo size in QR code as fraction of QR width (1.0 = 100%), default 0.25 \DeclareStringOption[0.02]{qrlogoborder} % white padding around logo in QR as fraction of QR width (1.0 = 100%), default 0.02 \DeclareStringOption{logoheight} % logo height next to name (with unit, e.g., 4em), default: 4em if company set, 2em otherwise \DeclareStringOption[1.0]{bgscale} % background image scale (1.0 = 100% card height), default 1.0 \DeclareStringOption[1.0]{bgopacity} % background image opacity (1.0 = 100% visible, 0.0 = invisible), default 1.0 \DeclareStringOption[1.0]{qrbgopacity} % QR code background opacity (1.0 = white solid, 0.0 = transparent), default 1.0 \DeclareStringOption[de]{lang} \DeclareBoolOption[false]{ioscrlf} % use CRLF line endings in vCard (iOS compatibility); default off to avoid pdfTeX issues \DeclareBoolOption[true]{address} \DeclareComplementaryOption{noaddress}{address} \DeclareBoolOption[true]{hint} \DeclareComplementaryOption{nohint}{hint} \DeclareBoolOption[true]{icon} \DeclareComplementaryOption{noicon}{icon} \DeclareBoolOption[true]{rightalign} \DeclareComplementaryOption{leftalign}{rightalign} \DeclareBoolOption[true]{iconleft} \DeclareComplementaryOption{iconright}{iconleft} \DeclareBoolOption[true]{fill} \DeclareComplementaryOption{nofill}{fill} \DeclareBoolOption[true]{qrfirst} \DeclareComplementaryOption{textfirst}{qrfirst} \DeclareBoolOption[true]{https} \DeclareComplementaryOption{www}{https} \DeclareStringOption[auto]{countryformat} % auto: <4 chars inline with mdash, >=4 separate line; inline: always inline; below: always separate line \DeclareDefaultOption{\@unknownoptionerror} \ProcessKeyvalOptions* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % definitions from the options \def\content{paperwidth=\BCQ@contentwidth,paperheight=\BCQ@contentheight} \def\papersize{width=\BCQ@paperwidth,height=\BCQ@paperheight} \def\padding{\BCQ@padding} % padding around the content \def\border{\BCQ@cutdist} % distance between start of cutmark and content in mm \def\cutlen{\BCQ@cutlen} % length of ct marks in mm \def\textpercents{\BCQ@textwidth} % size of text part 0..1 \def\imagepercents{\BCQ@qrwidth} % size of qrcode image part 0..1 \def\lang{\BCQ@lang} \def\protdisplay{\ifBCQ@https https://\else www.\fi} \def\protprefix{\ifBCQ@https https://\fi} \ifBCQ@address\def\printaddress{}\fi %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % global dependencies and settings \LoadClass[\BCQ@fontsize]{extarticle} \RequirePackage{marvosym} \RequirePackage{fontawesome} \RequirePackage[final]{qrcode} \RequirePackage{etoolbox} \RequirePackage{xstring} % for string length checking \RequirePackage{DejaVuSans} \RequirePackage[T1]{fontenc} \RequirePackage{wrapfig} \RequirePackage{graphicx} % needed for optional logo \RequirePackage{tikz} % needed for logo overlay in QR code \RequirePackage{eso-pic} % needed for background images without layout impact % Fix XeLaTeX opacity issue: ensure TikZ/PGF is loaded before eso-pic uses opacity \DeclareHookRule{shipout/background}{pgfrcs}{>}{eso-pic} \RequirePackage[\content,top=\padding,left=\padding,right=\padding,bottom=\padding]{geometry} %\RequirePackage{pbox} \RequirePackage{varwidth} \RequirePackage{calc} \pagestyle{empty} \setlength{\parindent}{0pt} \renewcommand*\familydefault{\sfdefault} \setlength{\fboxsep}{0pt} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % data registration \newcommand\BCQ@datareset{% \def\BCQ@data@hide{}% \def\BCQ@data@logo{}% \def\BCQ@data@height{}% } \define@key{BCQ@data}{hide}[true]{% \edef\BCQ@data@hide{#1}% } \define@key{BCQ@data}{logo}{% \def\BCQ@data@logo{#1}% } \define@key{BCQ@data}{height}{% \def\BCQ@data@height{#1}% } \newlength{\BCQ@companybrandingheight} \setlength{\BCQ@companybrandingheight}{2em} \newcommand\BCQ@applycompanyoptions{% \csundef{Xcompanylogo}% \csundef{Xcompanylogoheight}% \setlength{\BCQ@companybrandingheight}{2em}% \ifx\BCQ@data@logo\@empty\else \let\Xcompanylogo\BCQ@data@logo \ifx\BCQ@data@height\@empty \def\Xcompanylogoheight{1.5em}% \else \def\Xcompanylogoheight{\BCQ@data@height}% \fi \setlength{\BCQ@companybrandingheight}{\Xcompanylogoheight}% \fi } \newcommand\registerData[1]{% \expandafter\newcommand\csname #1\endcsname[2][]{% \BCQ@datareset \edef\BCQ@data@options{##1}% \ifx\BCQ@data@options\@empty\else \setkeys{BCQ@data}{##1}% \fi \csundef{X#1@hide}% \ifx\BCQ@data@hide\@empty\else \edef\BCQ@data@hidetmp{\BCQ@data@hide}% \ifdefstring{\BCQ@data@hidetmp}{false}{}{% \expandafter\def\csname X#1@hide\endcsname{true}% }% \fi \expandafter\def\csname X#1\endcsname{##2}% \ifstrequal{#1}{company}{\BCQ@applycompanyoptions}{}% }% } \registerData{type} \registerData{givennames} \registerData{familynames} \registerData{honoricprefix} \registerData{honoricsuffix} \registerData{company} \registerData{additionalnames} \registerData{pobox} \registerData{role} \registerData{extaddr} \registerData{street} \registerData{city} \registerData{region} \registerData{zip} \registerData{country} \registerData{phone} \registerData{email} \registerData{jabber} \registerData{matrixorg} \registerData{cloud} \registerData{homepage} \registerData{wordpress} \registerData{drupal} \registerData{joomla} \registerData{wikipedia} \registerData{link} \registerData{world} \registerData{git} \registerData{gitea} \registerData{github} \registerData{facebook} \registerData{twitter} \registerData{youtube} \registerData{google} \registerData{pgpurl} \registerData{pgpfingerprint} % Override document \title to capture card title (original available via \carddocumenttitle) \let\BCQ@documenttitle\title \renewcommand\title[1]{% \def\Xtitle{#1}% } \newcommand\carddocumenttitle[1]{% \BCQ@documenttitle{#1}% } % Special commands with optional parameters % \logo[height=...]{file} - logo next to name, overrides logoheight option \define@key{BCQ@logo}{height}{\def\BCQ@logoheight@local{#1}} \newcommand\logo[2][]{ \def\Xlogo{#2} \def\BCQ@logo@tmp{#1}% \ifx\BCQ@logo@tmp\@empty\else \setkeys{BCQ@logo}{#1} \fi } % \qrlogo[scale=...,opacity=...]{file} - logo in QR code center (scale is unitless fraction like 0.3) \define@key{BCQ@qrlogo}{scale}{\def\BCQ@qrlogoscale@local{#1}} \define@key{BCQ@qrlogo}{opacity}{\def\BCQ@qrbgopacity@local{#1}} \newcommand\qrlogo[2][]{ \def\Xqrlogo{#2} \def\BCQ@qrlogo@tmp{#1}% \ifx\BCQ@qrlogo@tmp\@empty\else \setkeys{BCQ@qrlogo}{#1} \fi } % \background[scale=...,opacity=...]{file/color} - background image or color \define@key{BCQ@background}{scale}{\def\BCQ@bgscale@local{#1}} \define@key{BCQ@background}{opacity}{\def\BCQ@bgopacity@local{#1}} \newcommand\background[2][]{ \def\Xbackground{#2} \def\BCQ@background@tmp{#1}% \ifx\BCQ@background@tmp\@empty\else \setkeys{BCQ@background}{#1} \fi } \registerData{companylogo} % content (image/object) to display instead of company text (company still in vCard) \define@key{BCQ@companylogo}{height}{% \def\BCQ@companylogo@height{#1}% } \renewcommand\companylogo[2][]{% \def\BCQ@companylogo@height{}% \edef\BCQ@companylogo@options{#1}% \ifx\BCQ@companylogo@options\@empty\else \setkeys{BCQ@companylogo}{#1}% \fi \def\Xcompanylogo{#2}% \ifx\BCQ@companylogo@height\@empty \def\Xcompanylogoheight{1.5em}% \else \def\Xcompanylogoheight{\BCQ@companylogo@height}% \fi \setlength{\BCQ@companybrandingheight}{\Xcompanylogoheight}% } \newcommand\ifvisible[3]{% \ifcsdef{#1}{% \ifcsdef{#1@hide}{#3}{#2}% }{#3}% } \newcommand\conddisplay[1]{% \ifvisible{#1}{\exec{#1}}{}% } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % auxiliary commands \newcommand\enforceright{\leftskip0pt plus 1fill\rightskip0pt} \newcommand\exec[1]{\csname #1\endcsname} \newcommand\insa[3][]{\ifvisible{#2}{ \ifBCQ@iconleft \ifBCQ@icon\parbox{1em}{\centering\exec{#3}}\ \fi\ifBCQ@hint{\tiny#1}\fi\ifBCQ@fill\hfill\fi\exec{#2} \else \ifBCQ@hint{\tiny#1\ }\fi\exec{#2}\ifBCQ@fill\hfill\fi\ifBCQ@icon\ \parbox{1em}{\centering\exec{#3}}\fi \fi }{}} \newcommand\ifexists[2]{\ifcsdef{#1}{#2}{}} \newcommand\ifboth[3]{\ifcsdef{#1}{\ifcsdef{#2}{#3}{}}{}} \newcommand\ifany[3]{\ifcsdef{#1}{#3}{\ifcsdef{#2}{#3}{}}} \newcommand\cond[1]{\ifcsdef{#1}{\exec{#1}}{}} % internal boxes and lengths for measuring \newsavebox{\BCQ@namebox} \newsavebox{\BCQ@logobox} \newlength{\BCQ@logoheightdimen} \setlength{\BCQ@logoheightdimen}{0pt}% initialize to prevent errors \newlength{\BCQ@reservedheight} \newlength{\BCQ@heightscale} \newlength{\BCQ@namewidth} \newlength{\BCQ@logosep} \newlength{\BCQ@logosepused} \setlength{\BCQ@logosep}{1em} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % name - assemble full name from the parts, such as Xgivennames and Xfamilynames \newcommand\personalnamevcard{% \ifexists{Xhonoricprefix}{\Xhonoricprefix\ }% \ifexists{Xgivennames}{\Xgivennames\ }% \ifexists{Xadditionalnames}{\Xadditionalnames\ }% \ifexists{Xfamilynames}{\Xfamilynames}% \ifexists{Xhonoricsuffix}{\ \Xhonoricsuffix}% } \newcommand\personalname{% \ifvisible{Xhonoricprefix}{\Xhonoricprefix\ }{}% \ifvisible{Xgivennames}{\Xgivennames\ }{}% \ifvisible{Xadditionalnames}{\Xadditionalnames\ }{}% \ifvisible{Xfamilynames}{\Xfamilynames}{}% \ifvisible{Xhonoricsuffix}{\ \Xhonoricsuffix}{}% } \newcommand\ifhaspersonalname[2]{% \ifvisible{Xhonoricprefix}{#1}{% \ifvisible{Xgivennames}{#1}{% \ifvisible{Xadditionalnames}{#1}{% \ifvisible{Xfamilynames}{#1}{% \ifvisible{Xhonoricsuffix}{#1}{#2}% }% }% }% }% } \newcommand\ifhaspositiontext[2]{% \ifvisible{Xcompany}{#1}{% \ifvisible{Xtitle}{#1}{% \ifvisible{Xrole}{#1}{#2}% }% }% } \newcommand\ifhaspositionblock[2]{% \ifhaspositiontext{#1}{% \ifcsdef{Xcompanylogo}{#1}{#2}% }% } \newcommand\ifhaspersonalnamevcard[2]{% \ifcsname Xhonoricprefix\endcsname #1% \else\ifcsname Xgivennames\endcsname #1% \else\ifcsname Xadditionalnames\endcsname #1% \else\ifcsname Xfamilynames\endcsname #1% \else\ifcsname Xhonoricsuffix\endcsname #1% \else #2% \fi\fi\fi\fi\fi } % heightscale - calculate available height for text/QR % Uses actual logo height if logo is taller than default reserved space % This is computed as a length and stored, not a macro \newcommand\computeheightscale{% \setlength{\BCQ@reservedheight}{\dimexpr\ifhaspersonalname{2em}{0em}+\ifhaspositionblock{\BCQ@companybrandingheight}{0pt}\relax}% \ifdim\BCQ@logoheightdimen>\BCQ@reservedheight \setlength{\BCQ@heightscale}{\dimexpr\textheight-\BCQ@logoheightdimen-\ifcsdef{Xpgpfingerprint}{2em}{0em}\relax}% \else \setlength{\BCQ@heightscale}{\dimexpr\textheight-\BCQ@reservedheight-\ifcsdef{Xpgpfingerprint}{2em}{0em}\relax}% \fi } \newcommand\heightscale{\BCQ@heightscale} \newcommand\companyrolestringdisplay{% \ifvisible{Xtitle}{\Xtitle}{}% \ifvisible{Xrole}{% \ifvisible{Xtitle}{, }{}% \Xrole }{}% \ifvisible{Xcompany}{% \ifvisible{Xtitle}{\ \Xcompany}{% \ifvisible{Xrole}{\ \Xcompany}{\Xcompany}% }% }{}% } \newcommand\companybrandingline{% \ifcsdef{Xcompanylogo}{\companylogocontent}{}% \ifhaspositiontext{% \ifcsdef{Xcompanylogo}{\hspace{0.5em}}{}% \companyrolestringdisplay }{}% } \newcommand\companyrolestringvcard{% \ifcsname Xtitle\endcsname \Xtitle \fi \ifcsname Xrole\endcsname \ifcsname Xtitle\endcsname , \fi \Xrole \fi \ifcsname Xcompany\endcsname \ifcsname Xtitle\endcsname \ \Xcompany \else \ifcsname Xrole\endcsname \ \Xcompany \else \Xcompany \fi \fi \fi } \newcommand\displayname{% \ifhaspersonalname{\personalname}{\companybrandingline}% } \newcommand\BCQ@appendvcardposition{% \ifhaspersonalnamevcard{% \ (\companyrolestringvcard)% }{% \companyrolestringvcard }% } \newcommand\BCQ@buildname{% \ifhaspersonalnamevcard{% \personalnamevcard \ifcsname Xtitle\endcsname \BCQ@appendvcardposition \else \ifcsname Xrole\endcsname \BCQ@appendvcardposition \else \ifcsname Xcompany\endcsname \BCQ@appendvcardposition \fi \fi \fi }{% \companyrolestringvcard }% } \let\BCQ@cachedname\@empty \newcommand\BCQ@setnamecache{% \begingroup \edef\BCQ@tmp{\BCQ@buildname}% \global\let\BCQ@cachedname\BCQ@tmp \endgroup } \newcommand\name{% \ifx\BCQ@cachedname\@empty \BCQ@buildname \else \BCQ@cachedname \fi } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % vcard - the content of the vcard % 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\BCQ@nl \ifexists{Xcompany}{ORG:\Xcompany\BCQ@nl} \ifexists{Xtitle}{TITLE:\Xtitle\BCQ@nl} \ifexists{Xrole}{ROLE:\Xrole\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} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % formatcountry - format country based on length and options \newcommand\formatcountry{% \ifcsdef{Xcountry}{% \ifvisible{Xcountry}{% \def\BCQ@shouldinline{false}% \def\BCQ@haszipcity{false}% \ifvisible{Xcity}{\def\BCQ@haszipcity{true}}{}% \ifvisible{Xzip}{\def\BCQ@haszipcity{true}}{}% % Check countryformat option \ifdefstring{\BCQ@countryformat}{inline}{% \def\BCQ@shouldinline{true}% }{% \ifdefstring{\BCQ@countryformat}{below}{% \def\BCQ@shouldinline{false}% }{% % auto mode: check length \StrLen{\Xcountry}[\BCQ@countrylen]% \ifnum\BCQ@countrylen<4\relax% % Short country code AND city/zip exists → inline \ifdefstring{\BCQ@haszipcity}{true}{% \def\BCQ@shouldinline{true}% }{}% \fi% }% }% % Output country \ifdefstring{\BCQ@shouldinline}{true}{% \Xcountry\ \textemdash\ \conddisplay{Xzip} \conddisplay{Xcity}% }{% \conddisplay{Xzip} \conddisplay{Xcity} \Xcountry }% }{% \conddisplay{Xzip} \conddisplay{Xcity}% }% }{ \conddisplay{Xzip} \conddisplay{Xcity}% }% } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % address - the address as shown in the textbox \newcommand\address{ \conddisplay{Xpobox} \conddisplay{Xextaddr} \conddisplay{Xstreet} \formatcountry \conddisplay{Xregion} } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % inserttext - assemble the textbox \newcommand\inserttext{ %\frame { \begin{minipage}[c][\heightscale][c]{\textpercents\textwidth} \ifBCQ@rightalign\begin{flushright}\fi \ifexists{printaddress}{ \ifBCQ@iconleft \ifBCQ@icon\parbox[c]{1em}{\faMapMarker}\ \ifBCQ@fill\hfill\fi\fi %\frame{ %\pbox[t]{\dimexpr\textwidth-2em\relax}{ \begin{varwidth}{\dimexpr\textwidth-2em\relax} \ifBCQ@rightalign\enforceright\fi\address \end{varwidth} %} %} \else %\pbox[t]{\dimexpr\textwidth-2em\relax}{ \begin{varwidth}{\dimexpr\textwidth-2em\relax} \ifBCQ@rightalign\enforceright\fi\address \end{varwidth} %} \ifBCQ@icon\ifBCQ@fill\hfill\fi\ \parbox[c]{1em}{\faMapMarker}\fi \fi \vspace{1em} } \insa[tel:]{Xphone}{faMobile}\insa[mailto:]{Xemail}{Email}\insa[xmpp]{Xjabber}{faCommentsO}\insa[matrix.org]{Xmatrixorg}{faCommentsO}\insa[nextcloud-id]{Xcloud}{faCloud}\insa[\protdisplay]{Xhomepage}{faHome}\insa[\protdisplay]{Xwordpress}{faWordpress}\insa[\protdisplay]{Xdrupal}{faDrupal}\insa[\protdisplay]{Xjoomla}{faJoomla}\insa[{\protprefix}\lang.wikipedia.org/wiki/]{Xwikipedia}{faWikipediaW}\insa[\protdisplay]{Xlink}{faLink}\insa[\protdisplay]{Xworld}{faGlobe}\insa[\protdisplay]{Xgit}{faGit}\insa[\protdisplay]{Xgitea}{faGithubAlt}\insa[{\protprefix}github.com/]{Xgithub}{faGithub}\insa[{\protprefix}facebook.com/]{Xfacebook}{faFacebook}\insa[{\protprefix}twitter.com/]{Xtwitter}{faTwitter}\insa[{\protprefix}youtube.com/user/]{Xyoutube}{faYoutube}\insa[{\protprefix}plus.google.com/+]{Xgoogle}{faGooglePlus} \ifBCQ@rightalign\end{flushright}\fi \end{minipage} } } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % insertqrcode - insert the qr-code with optional white background \newcommand\insertqrcode{ % Use local overrides if specified, otherwise use global options \ifcsdef{BCQ@qrbgopacity@local}{% \edef\BCQ@qrbgopacity@used{\BCQ@qrbgopacity@local}% }{% \edef\BCQ@qrbgopacity@used{\BCQ@qrbgopacity}% }% \ifcsdef{BCQ@qrlogoscale@local}{% \edef\BCQ@qrlogoscale@used{\BCQ@qrlogoscale@local}% }{% \edef\BCQ@qrlogoscale@used{\BCQ@qrlogoscale}% }% %\frame { \begin{minipage}[c][\heightscale][c]{\imagepercents\textwidth} \begin{tikzpicture} % White background behind QR code (for readability over background images) \node[fill=white, opacity=\fpeval{\BCQ@qrbgopacity@used}, inner sep=0pt, outer sep=2mm, minimum size=\textwidth] (bg) at (0,0) {}; % QR code on top \node[inner sep=0pt, outer sep=0pt] (qr) at (0,0) {% % QR code with optional qrlogo overlay in center \ifcsdef{Xqrlogo}{% \begin{tikzpicture} \node[inner sep=0pt] (qr2) {\qrcode[level=\BCQ@qreclevel,version=0,height=\textwidth]{\vcard}}; % Logo with transparent background preserved (no fill), padding still applied % qrlogoscale/scale is unitless fraction (0.25 = 25% of QR width) \node[inner sep=\BCQ@qrlogoborder\textwidth] at (qr2.center) {% \includegraphics[width=\BCQ@qrlogoscale@used\textwidth]{\Xqrlogo}% }; \end{tikzpicture}% }{% % No qrlogo defined, just show QR code \qrcode[level=\BCQ@qreclevel,version=0,height=\textwidth]{\vcard}% }% }; \end{tikzpicture} \end{minipage} } } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % insertname - insert the name on the top \newcommand\insertname{ % typeset name into box for measurement \sbox{\BCQ@namebox}{\bfseries\cond{displayname}}% % Set default logoheight if not specified: 4em with company, 2em without \ifx\BCQ@logoheight\@empty \ifcsdef{Xcompany}{\def\BCQ@logoheight{4em}}{\def\BCQ@logoheight{2em}}% \fi % Use local height override if specified, otherwise use global logoheight \ifcsdef{BCQ@logoheight@local}{% \edef\BCQ@logoheight@used{\BCQ@logoheight@local}% }{% \edef\BCQ@logoheight@used{\BCQ@logoheight}% }% % Store logo height as dimension for heightscale calculation \ifcsdef{Xlogo}{% \sbox{\BCQ@logobox}{\includegraphics[height=\BCQ@logoheight@used]{\Xlogo}}% \setlength{\BCQ@logoheightdimen}{\BCQ@logoheight@used}% }{% \setlength{\BCQ@logoheightdimen}{0pt}% }% % Compute heightscale after logo height is known \computeheightscale \ifcsdef{Xlogo}{% logo defined % Logo next to name: dynamic columns (logo natural width, name uses remaining space) \setlength{\BCQ@logosepused}{\BCQ@logosep}% \setlength{\BCQ@namewidth}{\dimexpr\textwidth-\wd\BCQ@logobox-\BCQ@logosepused\relax}% \ifdim\BCQ@namewidth<0pt \setlength{\BCQ@logosepused}{0pt}% \setlength{\BCQ@namewidth}{\dimexpr\textwidth-\wd\BCQ@logobox\relax}% \ifdim\BCQ@namewidth<0pt\setlength{\BCQ@namewidth}{0pt}\fi \fi \begin{minipage}{\textwidth} \begin{minipage}[c]{\wd\BCQ@logobox}% logo column \usebox{\BCQ@logobox}% \end{minipage} \hspace{\BCQ@logosepused} \begin{minipage}[c]{\BCQ@namewidth}% name column \ifBCQ@rightalign\raggedleft\fi% apply alignment {\bfseries\cond{displayname}}% \ifhaspersonalname{% \ifhaspositionblock{\\\companybrandingline}{}% }{}% \end{minipage} \end{minipage} }{% no logo: just name {\bfseries\cond{displayname}}% \ifhaspersonalname{% \ifhaspositionblock{\\\companybrandingline}{}% }{}% } } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % drawcardcontent - assemble all blocks (name, text, qr, pgp) \newcommand\drawcardcontent{ \BCQ@setnamecache \ifBCQ@rightalign\begin{flushright}\fi \insertname \noindent\makebox[\linewidth]{\rule{\paperwidth}{0.4pt}} % horizontal line \vfill \ifBCQ@qrfirst \insertqrcode \hfill \inserttext \else \inserttext \hfill \insertqrcode \fi \ifexists{Xpgpfingerprint}{ \vfill \ifBCQ@iconleft \faLock\ifBCQ@hint{\tiny\ pgp}\fi\hfill{\small\Xpgpfingerprint} \else {\small\Xpgpfingerprint}\hfill\ifBCQ@hint{\tiny{pgp\ }}\fi\faLock \fi } \ifBCQ@rightalign\end{flushright}\fi } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % drawcard - main card with optional background \newcommand\drawcard{ % Use local overrides if specified, otherwise use global options \ifcsdef{BCQ@bgscale@local}{% \edef\BCQ@bgscale@used{\BCQ@bgscale@local}% }{% \edef\BCQ@bgscale@used{\BCQ@bgscale}% }% \ifcsdef{BCQ@bgopacity@local}{% \edef\BCQ@bgopacity@used{\BCQ@bgopacity@local}% }{% \edef\BCQ@bgopacity@used{\BCQ@bgopacity}% }% % Handle background \ifcsdef{Xbackground}{% \IfFileExists{\Xbackground}{% % It's an image file: add to background using eso-pic (no layout impact) \AddToShipoutPictureBG*{% \AtPageCenter{% \begin{tikzpicture}[overlay] \node[inner sep=0pt, opacity=\fpeval{\BCQ@bgopacity@used}] at (0,0) {% \includegraphics[height=\fpeval{\BCQ@bgscale@used}\paperheight]{\Xbackground}% }; \end{tikzpicture}% }% }% }{% % Not a file: treat as color \pagecolor{\Xbackground}% }% }{}% % Draw card content \drawcardcontent } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % cut / crop marks \RequirePackage[\papersize,noinfo,center,pdftex]{crop} \newcommand\tl{ \begin{picture}(0,0) \thinlines\unitlength1mm \put(-\border,0){\line(1,0){\cutlen}} \put(0,\border){\line(0,-1){\cutlen}} \end{picture} } \newcommand\tr{ \begin{picture}(0,0) \thinlines\unitlength1mm \put(\border,0){\line(-1,0){\cutlen}} \put(0,\border){\line(0,-1){\cutlen}} \end{picture} } \newcommand\bl{ \begin{picture}(0,0) \thinlines\unitlength1mm \put(-\border,0){\line(1,0){\cutlen}} \put(0,-\border){\line(0,1){\cutlen}} \end{picture} } \newcommand\br{ \begin{picture}(0,0) \thinlines\unitlength1mm \put(\border,0){\line(-1,0){\cutlen}} \put(0,-\border){\line(0,1){\cutlen}} \end{picture} } \cropdef[]\tl\tr\bl\br{cut} \crop[cut] \newcommand\companylogocontent{% \begingroup \edef\BCQ@companylogoscan{\expandafter\detokenize\expandafter{\Xcompanylogo}}% \IfSubStr{\BCQ@companylogoscan}{\string\\}{% \endgroup \Xcompanylogo }{% \xdef\BCQ@companylogopath{\BCQ@companylogoscan}% \endgroup \IfFileExists{\BCQ@companylogopath}{% \edef\BCQ@companylogoheightused{1.5em}% \ifcsdef{Xcompanylogoheight}{% \edef\BCQ@companylogoheightused{\Xcompanylogoheight}% }{}% \includegraphics[height=\BCQ@companylogoheightused]{\BCQ@companylogopath}% }{% \Xcompanylogo }% }% }